Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // This code demonstrates how associated types can create
- // conditionally-infinitely-sized types.
- //
- // This in turn can be used to logically prove a condition to be false, by
- // including a type that would have infinite size (and therefore be uninstantiable)
- // under that condition.
- //
- // Rust does not however use uninstantiability when trying to prove that two
- // blanket implementations of a trait cannot overlap, so alas this is just
- // an "interesting fact" today.
- // Something with an associated type
- trait Backend {
- type Metadata;
- }
- // A generic backend handler that stores the associated type
- struct SuperBackend<B: Backend> {
- metadata: B::Metadata,
- }
- // Someone's evil Backend that just wraps back around to the generic handler
- struct EvilBackend { }
- impl Backend for EvilBackend {
- type Metadata = SuperBackend<EvilBackend>;
- }
- // Trying to instantiate SuperBackend with an EvilBackend will always fail
- // static x: Option<SuperBackend<EvilBackend>> = None;
- //
- // error[E0275]: overflow evaluating the requirement `SuperBackend<EvilBackend>: std::marker::Sized`
- // (infinite sized type)
- // Meanwhile, we are prevented from writing this implementation of Borrow:
- impl<B: Backend> ::std::borrow::Borrow<B::Metadata> for SuperBackend<B> {
- fn borrow(&self) -> &B::Metadata {
- &self.backend
- }
- }
- /*
- error[E0119]: conflicting implementations of trait `std::borrow::Borrow<SuperBackend<_>>` for type `SuperBackend<_>`:
- --> src/lib.rs:24:1
- |
- 24 | impl<B: Backend> ::std::borrow::Borrow<B::Metadata> for SuperBackend<B> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: conflicting implementation in crate `core`:
- - impl<T> std::borrow::Borrow<T> for T
- where T: ?Sized;
- */
- // This error is effectively saying:
- // If B::Metadata were SuperBackend<B>, then this would be Borrow<Self>
- // which would overlap with the Borrow<Self> blanket implementation in `core`.
- //
- // We cannot eliminate this possibility (indeed, we wrote EvilBackend with
- // exactly that implementation), so we are forced to reject these two implementations
- // as potentially overlapping.
- //
- // Interestingly it would arguably be legal for the compiler to reason that
- // this implementation does not exist *in the context of SuperBackend*, because
- // it is impossible to instantiate SuperBackend<EvilBackend> due to its infinite size!
Add Comment
Please, Sign In to add comment