Guest User

Untitled

a guest
Dec 9th, 2018
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.36 KB | None | 0 0
  1. // This code demonstrates how associated types can create
  2. // conditionally-infinitely-sized types.
  3. //
  4. // This in turn can be used to logically prove a condition to be false, by
  5. // including a type that would have infinite size (and therefore be uninstantiable)
  6. // under that condition.
  7. //
  8. // Rust does not however use uninstantiability when trying to prove that two
  9. // blanket implementations of a trait cannot overlap, so alas this is just
  10. // an "interesting fact" today.
  11.  
  12. // Something with an associated type
  13. trait Backend {
  14. type Metadata;
  15. }
  16.  
  17. // A generic backend handler that stores the associated type
  18. struct SuperBackend<B: Backend> {
  19. metadata: B::Metadata,
  20. }
  21.  
  22. // Someone's evil Backend that just wraps back around to the generic handler
  23. struct EvilBackend { }
  24. impl Backend for EvilBackend {
  25. type Metadata = SuperBackend<EvilBackend>;
  26. }
  27.  
  28. // Trying to instantiate SuperBackend with an EvilBackend will always fail
  29. // static x: Option<SuperBackend<EvilBackend>> = None;
  30. //
  31. // error[E0275]: overflow evaluating the requirement `SuperBackend<EvilBackend>: std::marker::Sized`
  32. // (infinite sized type)
  33.  
  34. // Meanwhile, we are prevented from writing this implementation of Borrow:
  35. impl<B: Backend> ::std::borrow::Borrow<B::Metadata> for SuperBackend<B> {
  36. fn borrow(&self) -> &B::Metadata {
  37. &self.backend
  38. }
  39. }
  40.  
  41. /*
  42. error[E0119]: conflicting implementations of trait `std::borrow::Borrow<SuperBackend<_>>` for type `SuperBackend<_>`:
  43. --> src/lib.rs:24:1
  44. |
  45. 24 | impl<B: Backend> ::std::borrow::Borrow<B::Metadata> for SuperBackend<B> {
  46. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  47. |
  48. = note: conflicting implementation in crate `core`:
  49. - impl<T> std::borrow::Borrow<T> for T
  50. where T: ?Sized;
  51. */
  52.  
  53. // This error is effectively saying:
  54. // If B::Metadata were SuperBackend<B>, then this would be Borrow<Self>
  55. // which would overlap with the Borrow<Self> blanket implementation in `core`.
  56. //
  57. // We cannot eliminate this possibility (indeed, we wrote EvilBackend with
  58. // exactly that implementation), so we are forced to reject these two implementations
  59. // as potentially overlapping.
  60. //
  61. // Interestingly it would arguably be legal for the compiler to reason that
  62. // this implementation does not exist *in the context of SuperBackend*, because
  63. // it is impossible to instantiate SuperBackend<EvilBackend> due to its infinite size!
Add Comment
Please, Sign In to add comment