-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow inherent implementations on primitives, remove some extension traits #23104
Conversation
r? @brson (rust_highfive has picked a reviewer for you, use r? to override) |
Oh, and I haven't check what the documentation looks like. I expect that either (a) the inherent impl won't show up, (b) rustdoc will ICE or (c) the inherent impl will magically appear in libunicode. |
re: docs. The |
☔ The latest upstream changes (presumably #23107) made this pull request unmergeable. Please resolve the merge conflicts. |
This...is remarkably simple. I'm in favor. |
@japaric Sorry for not leaving a comment earlier -- I thought I had. I'm delighted to see this! It will definitely help remove a few warts in the final days of stabilization. I talked with @alexcrichton about it at lunch today and he's also on board, so since @nikomatsakis approves I'd say let's roll this out across the full set of primitive types (including numerics). Thanks! |
One part I'll also point out is that in the past when I dabbled with inherent methods on primitives I had to add special code to rustdoc to get things to work out. That may no longer be necessary, but could you give the primitive pages a quick glance to make sure all the methods are listed? |
@aturon Alright, I'll look into it. One worry is that I think it may not be possible to
I can't check right now, but I did check them before, and IIRC all the methods were listed. The issue was that there were two primitive |
Right, that's pretty much exactly the rollout plan I had in mind. Part of the motivation here is to do away with those traits within |
impl char
, remove unicode::CharExt
OK, this is mostly done. There is a summary of the changes at the top, along with a preview of the docs (I haven't look at them closely yet). This branch passes There is one caveat: Because How to deal with these tests? I see two alternatives right now: (a) we rewrite the tests to not access private fields, not sure if this is possible for all the tests, or (b) we move these tests back to libcollections, making this work can be tricky due to the original problem of conflicting lang items. I'll take a look at the second option tonight. cc @gankro Do you think it would be possible to modify the commented out tests [1] to not access private fields while retaining the intention of the tests? [1] See the "extract libcollections tests into libcollectionstest" commit, the tests are marked with "FIXME(japaric) privacy". |
I would favor this wherever possible, although it probably depends on the test.
For a particular test it may not be too hard to get it to work, even with lang items. But it also depends on the test :) |
Oof, migrating some of these tests would be really nasty. One option is to expose privates in For specific tests: The Vec::permutations one I'd probably just toss the offending check as "whatever" (I'd also toss the permutations api myself but that's just me). LinkedList's integrity check could be made a doc(hidden) test, although honestly I don't think it's particularly necessary to perform the check at all. LinkedList is my nemesis but it's not exactly mind-blowing complexity. Also you can emulate the checks by just providing a slice of the expected values and iterating forwards and backwards. VecDeque is probably the toughest case. We totally abuse access to the internals for two things: minimum-cost bench resets, and enumerating every possible internal state of the Deque. In theory you could do a whole mess of pushy-pops to slide the head of the list to exactly the right position, but that would perhaps be a bit fragile on top of being slower and more tedious. The check that I don't see why enum_set is commented out; it looks like everything there is using the public API? |
I'm generally opposed to this idea,
My bad, I was importing
Ok, I'll try to move these tests back to libcollections then. Thanks for the input @gankro! |
I've re-enabled the tests after moving them back to libcollections (see two last commits). I'll double check the docs and rebase after that. But the review process can already start ;-). |
String { vec: <[_]>::to_vec(string.as_bytes()) } | ||
} | ||
|
||
// HACK: `impl [T]` is not available in cfg(test), use `::slice::to_vec` instead of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this just a staging issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, no. To avoid conflicting lang items during unit testing, I had to mark the impl [T]
with cfg(not(test))
. Therefore during testing the methods that were in impl [T]
but not in core::slice::SliceExt
need to be resupplied as free functions. These free functions are only ever available and used during testing - so they shouldn't leak into the public API. (I left a comment explaining this in libcollections/slice.rs - but you can't see that file here beacuse of the huge diff)
Woot! Does rustdoc handle these impls in some non-terrible way? |
Yes, they appear as a a normal |
Sweet. Looks good to me, but someone else should take a look at the rustc changes. |
@sfackler Thanks for taking a look! This has been carefully rebased over the char stabilization PR, now all the |
I can r? |
#[unstable(feature = "collections", | ||
reason = "needs investigation to see if to_string() can match perf")] | ||
#[cfg(not(test))] | ||
pub fn from_str(string: &str) -> String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a bit confused -- why is this PR adding these fns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, well, I guess they already exist -- I didn't (and don't) see them in the deletions though, which is weird.
I'm starting to somewhat have second thoughts about this from a compiler implementation perspective. From an API standpoint I think this change is fine largely because it doesn't really change much. Overall, however, this seems like it's all a bit of a hack. We're basically bending the language to our whim to enable this sort of functionality because we control the compiler, but from the perspective of some other hypothetical compiler implementor this becomes quite a pain. We're adding all these special cases for these very implementation-specific set of I think the biggest pain points for me when reading this are:
The lang item problem can probably be considered an implementation detail of the compiler, but allowing multiple inherent implementations makes me feel like something has gone awry somewhere. We don't have the luxury of always being able to bend the language so API design is a little easier, and I felt that the previous trait-per-primitive-in-the-prelude solution was quite adequate: it worked out well in terms of documentation, functionality, extensibility, and it was also consistent with the rest of the language. |
Are any crate now allowed to have inherent implementations for primitive types? If not, what is the rule that allows e.g. libunicode to do it? |
@SimonSapin The rule is effectively: a single crate within the |
@SimonSapin To expand on @aturon's answer: it's done with That means no crate using libstd can add methods to any of the primitives supporting this mechanism. |
That sounds reasonable. Thanks for the explanation! |
PR rust-lang#23104 moved `is_null` and `offset` to an inherent impl on the raw pointer type.
PR rust-lang#23104 moved `is_null` and `offset` to an inherent impl on the raw pointer type. I'm not sure whether or how it's possible to link to docs for that impl. r? @steveklabnik
PR rust-lang#23104 moved `is_null` and `offset` to an inherent impl on the raw pointer type. I'm not sure whether or how it's possible to link to docs for that impl. r? @steveklabnik
In Rust primitive types are only allowed a single impl block that must be annotated with lang attribute We do not enforce this yet an accept user defined impl blocks. See rust-lang/rust#23104 and the error code E0390. The primitive type bool does not have an impl block / lang attribute. TODO: * Clean up a lot * Combine the 2 find methods * Missing primitive types: slice, const_ptr, mut_ptr * Autocompletions on u8, i8, ... do not work as they are implemented by a macro * What fingerprint/string should we use for primitive types (to avoid overlap with user defined types) * Incomplete tests
In Rust primitive types are only allowed a single impl block that must be annotated with lang attribute We do not enforce this yet an accept user defined impl blocks. See rust-lang/rust#23104 and the error code E0390. The primitive type bool does not have an impl block / lang attribute. TODO: * Clean up a lot * Combine the 2 find methods * Missing primitive types: slice, const_ptr, mut_ptr * Autocompletions on u8, i8, ... do not work as they are implemented by a macro * What fingerprint/string should we use for primitive types (to avoid overlap with user defined types) * Incomplete tests
impl blocks for primitive types are not correctly indexed. This causes problems with autocompletion and method resolving around primitive types. In Rust primitive types are only allowed a single impl block that must be annotated with the "lang" attribute. The primitive types bool does not have an inherent impl. See rust-lang/rust#23104 and the error code E0390 for more details. Our implementation does not enforce this limitation and also accept user defined impl blocks.
impl blocks for primitive types are not correctly indexed. This causes problems with autocompletion and method resolving around primitive types. In Rust primitive types are only allowed a single impl block that must be annotated with the "lang" attribute. The primitive types bool does not have an inherent impl. See rust-lang/rust#23104 and the error code E0390 for more details. Our implementation does not enforce this limitation and also accept user defined impl blocks.
…crum Classify BinaryHeap & LinkedList unit tests as such All but one of these so-called integration test case are unit tests, just like btree's were (rust-lang#75531). In addition, reunite the unit tests of linked_list that were split off during rust-lang#23104 because they needed to remain unit tests (they were later moved to the separate file they are in during rust-lang#63207). The two sets could remain separate files, but I opted to merge them back together, more or less in the order they used to be, apart from one duplicate name `test_split_off` and one duplicate tiny function `list_from`.
char
,str
,[T]
,*const T
,*mut T
and all the numeric primitives.unicode::char::CharExt
methods intoimpl char
unicode::char::CharExt
, its re-exportstd::char::CharExt
andCharExt
from the preludecollections::str::StrExt
methods intoimpl str
collections::str::StrExt
its re-exportstd::str::StrExt
, andStrExt
from the preludecollections::slice::SliceExt
methods intoimpl<T> [T]
collections::slice::SliceExt
its re-exportstd::slice::SliceExt
, andSliceExt
from the preludecore::ptr::PtrExt
methods intoimpl<T> *const T
core::ptr::PtrExt
its re-exportstd::ptr::PtrExt
, andPtrExt
from the preludecore::ptr::PtrExt
andcore::ptr::MutPtrExt
methods intoimpl<T> *mut T
core::ptr::MutPtrExt
its re-exportstd::ptr::MutPtrExt
, andMutPtrExt
from the preludecore::num::Int
andcore::num::SignedInt
methods intoimpl i{8,16,32,64,size}
core::num::Int
andcore::num::UnsignedInt
methods intoimpl u{8,16,32,64,size}
core::num::UnsignedInt
and its re-exportstd::num::UnsignedInt
collections
tests into its own crate:collectionstest
std::num::Float
methods intoimpl f{32,64}
Because this PR removes several traits, this is a [breaking-change], however functionality remains unchanged and breakage due to unresolved imports should be minimal. If you encounter an error due to an unresolved import, simply remove the import:
cc #16862
preview docs
unicode::char
collections::str
std::f32