-
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
Tracking issue for negative impls #68318
Comments
Odd possibly off topic question about this. The following compiles:
Should it? |
I would say no, because if you wanted to shift the error to runtime you could implement Drop as:
I generally like to catch anything at compile time that can be caught at compile time. |
According to the documentation
As a trait bound, (If you did not already know, drop glue is the term for all the code that Yes, the |
Not sure if this is the right place to report a bug with the current nightly implementation, but a negative implementation and its converse seem to "cancel each other out". For example: trait A {}
trait B {}
// logically equivalent negative impls
impl<T: A> !B for T {}
impl<T: B> !A for T {}
// this should not be possible, but compiles:
impl A for () {}
impl B for () {} The above compiles without errors on nightly, though it shouldn't. Removing one of the negative impls fixes the issue and results in an error as expected. |
Allowing negative trait bounds would make my code much better by allowing to express di- and poly-chotomy. In Rust 1.57.0 the following doesn't compile: #![feature(negative_impls)]
trait IntSubset {}
impl <T> IntSubset for T where T: FixedSizeIntSubset + !ArbitrarySizeIntSubset {}
impl <T> IntSubset for T where T: !FixedSizeIntSubset + ArbitrarySizeIntSubset {}
trait FixedSizeIntSubset {}
impl<T: FixedSizeIntSubset> !ArbitrarySizeIntSubset for T {}
trait ArbitrarySizeIntSubset {}
impl<T: ArbitrarySizeIntSubset> !FixedSizeIntSubset for T {} |
Coming here from a compiler error, how do I "use marker types" to indicate a struct is not Send on stable Rust? I don't see any "PhantomUnsend" or similar anywhere in std.
|
@mwerezak I think I've seen
|
@rMazeiks Thanks, I wouldn't have known really what type would be the appropriate choice to use with A |
I think we should just rule out |
Can we add "negative super traits" to the unwritten RFC? That is, pub trait Foo {}
pub trait Bar: !Foo {}
// We now know that the two traits are exclusive, thus can write:
trait X {}
impl<T: Foo> X for T {}
impl<T: Bar> X for T {} Quote from the Hackmd:
Negative super traits should get around this: the above snippet should work even if The potential issue here is that adding implementations to any trait exported by a library is technically a breaking change (though I believe it is already in some circumstances due to method resolution, and also is with any other aspect of negative trait bounds). |
I would prefer to leave that for future work, @dhardy -- I'd rather not open the door on negative where clauses just now, but also I think that it'd be interesting to discuss the best way to model mutually exclusive traits (e.g., maybe we want something that looks more like enums). |
Some objects in dlib are not Thread Safe, thus they should be marked as !Sync to do this in stable Rust, you add a field with `UnsafeCell`. If you don't need `UnsafeCell`, then just put it inside a `PhantomData`, this tells the type system that your type should act as if it held an `UnsafeCell`, but it doesn't actually have it. When [`negative_impls`](rust-lang/rust#68318) is stabilized, we can use that instead. I would suggest applying this patch then bumping the crate version to 0.3.1 and yanking 0.3.0 to prevent people from downloading the previous version.
This came up in the libs-api meeting today while we were discussing rust-lang/libs-team#175 which proposes adding How does the lang team feel about a partial stabilization of negative impls which only covers the specific use case of opting-out of OIBITs like |
For those who's wondering what OIBITs are,
Source: https://internals.rust-lang.org/t/pre-rfc-renaming-oibits-and-changing-their-declaration-syntax/3086 |
We discussed this in today's @rust-lang/lang meeting. We had a consensus in favor of stabilizing enough of negative impls here. The subset we'd be in favor of stabilizing would be to require that the negative impl be "always applicable". Effectively, the impls can't have any bounds other than those required for an instance of the type. So, if One further consideration: a negative impl |
To add to the @joshtriplett's comment:
I've also volunteered to work on stabilization of this feature and related work here. |
Are you proposing to also stabilize negative bounds (as a semver promise) for non-auto-traits? If not, how can removing a negative impl of an auto trait be a breaking change with any auto trait we have? |
More on "questionable" impls:
|
@ChayimFriedman2 no, negative bounds are a separate feature and there is no suggestions to stabilize that. The reason removing a negative impl is a breaking change is that typechecker is allowed to assume that it is. It currently doesn't use this AFAIK, but in the feature we want to allow code like this: struct NeverSend;
impl !Send for NeverSend {}
trait X {}
impl<T: Send> X for T {}
impl X for NeverSend {} // typechecked is allowed to assume those impl don't overlap |
@WaffleLapkin we were working on this with @lcnr and @nikomatsakis and at some point but the work was deferred. I'm happy if you can move this forward and I'd be interested in following along. I think I even have a couple of PRs about this half-baked that I'm not sure if are relevant anymore :). Feel free to reach out if I can help with things. There's also the RFC draft that we were working in meetings with Niko https://hackmd.io/ZmpF0ITPRWKx6jYxgCWS7g |
@spastorino How easily could we add |
from a t-types pov it's pretty straightforward to implement with the following design constraints
if t-lang decides that we should have that feature, it could be stabilized in 1-2 releases (assuming someone has the capacity to work) |
@lcnr 👍, my understanding was also that this is "easy" to do. I'd be up for working on this |
One possibility would be to allow such impls to be specialized by a more specific positive impl defined in the same crate. This would provide a way of expressing that a positive impl is guaranteed not to be extended or generalized in the future. |
@rustbot labels -I-lang-nominated We discussed this, as mentioned above, and the team was in favor of doing it. The next step would be someone putting together a concrete proposal, probably in the form of a stabilization PR with a suitably detailed stabilization report. Until then, there's probably not much more to discuss, so we'll remove the nomination. As soon as the stabilization report / PR is posted, please nominate for T-lang. |
Not sure if I like this syntax, but okay. It'd be nice if there was a way to have a negative trait bound, i.e. "P is a Parser but not a Combinator", but that's part of Rust unstable so far, rust-lang/rust#68318.
Generalized negative impls were introduced in #68004. They were split out from "opt-in builtin traits" (#13231).
Work in progress
This issue was added in advance of #68004 landed so that I could reference it from within the code. It will be closed if we opt not to go this direction. A writeup of the general feature is available in this hackmd, but it will need to be turned into a proper RFC before this can truly advance.
Current plans
!Drop
(negative impls ofDrop
)Unresolved questions to be addressed through design process
default impl !Trait for Type { }
? (Context)The text was updated successfully, but these errors were encountered: