3 releases
new 0.1.1 | Oct 31, 2024 |
---|---|
0.1.0 | Oct 31, 2024 |
#1647 in Rust patterns
273 downloads per month
12KB
::negative
Negative impl
s in stable Rust.
It can be useful to avoid the need to include an ugly PhantomData
:
/// Unit struct!
struct SyncButNotSend;
#[::negative::negative_impl]
unsafe impl !Send for SyncButNotSend {}
const _OK: &dyn Sync = &SyncButNotSend;
/// Error, `Send` is not implemented!
const _COMPILE_ERROR: &dyn Send = &SyncButNotSend;
But most importantly, it does change the semantics with regards to coherence (overlapping impl
s checker), since it makes the trait be explictly unimplemented, becoming a semver promise, rather than the default "this thing happens to be carrying a field type which itself happens not to be implementing said auto-trait yet, so let's make it so the resulting type does not implement saif auto-trait yet either".
struct Foo;
#[::negative::negative_impl]
impl !Unpin for Foo {}
trait Demo {}
impl<T : Unpin> Demo for T {}
impl Demo for Foo {} // <- does not overlap!
Indeed, the following, on the other hand, would fail to compile:
struct Foo(::core::marker::PhantomPinned);
trait Demo {}
impl<T : Unpin> Demo for T {}
impl Demo for Foo {} // <- Error, may overlap!
This is because the way stable Rust traditionally opts out of auto-traits is via lack-of-auto-trait-impl structural infection from Phantom
types.
But these types, as far as the coherence checker is concerned, just happen not to be implementing said traits in the current version of the stdlib, that is, they conservatively assume a future, semver-compatible, bump of the standard library may decide to add:
impl Unpin for PhantomPinned {}
Thus, it considers that:
-
in current Rust,
PhantomPinned : Unpin
does not hold; -
but in some future version of Rust,
PhantomPinned : Unpin
could hold.
Thus, as far as the coherence checker is concerned, rather than:
PhantomPinned : !Unpin
we actually have:
PhantomPinned : ?Unpin
- (and so on for all the other auto-traits.)
And thence, Foo : ?Unpin
, rather than Foo : !Unpin
.
Hence why <T : Unpin>
and Foo
are conservatively deemed to be able to overlap.
Dependencies
~280–740KB
~18K SLoC