![]() improve normalization of `Pointee::Metadata` This PR makes it so that `<Wrapper<Tail> as Pointee>::Metadata` is normalized to `<Tail as Pointee>::Metadata` if we don't know `Wrapper<Tail>: Sized`. With that, the trait solver can prove projection predicates like `<Wrapper<Tail> as Pointee>::Metadata == <Tail as Pointee>::Metadata`, which makes it possible to use the metadata APIs to cast between the tail and the wrapper: ```rust #![feature(ptr_metadata)] use std::ptr::{self, Pointee}; fn cast_same_meta<T: ?Sized, U: ?Sized>(ptr: *const T) -> *const U where T: Pointee<Metadata = <U as Pointee>::Metadata>, { let (thin, meta) = ptr.to_raw_parts(); ptr::from_raw_parts(thin, meta) } struct Wrapper<T: ?Sized>(T); fn cast_to_wrapper<T: ?Sized>(ptr: *const T) -> *const Wrapper<T> { cast_same_meta(ptr) } ``` Previously, this failed to compile: ``` error[E0271]: type mismatch resolving `<Wrapper<T> as Pointee>::Metadata == <T as Pointee>::Metadata` --> src/lib.rs:16:5 | 15 | fn cast_to_wrapper<T: ?Sized>(ptr: *const T) -> *const Wrapper<T> { | - found this type parameter 16 | cast_same_meta(ptr) | ^^^^^^^^^^^^^^ expected `Wrapper<T>`, found type parameter `T` | = note: expected associated type `<Wrapper<T> as Pointee>::Metadata` found associated type `<T as Pointee>::Metadata` = note: an associated type was expected, but a different one was found ``` (Yes, you can already do this with `as` casts. But using functions is so much ✨ *safer* ✨, because you can't change the metadata on accident.) --- This PR essentially changes the built-in impls of `Pointee` from this: ```rust // before impl Pointee for u8 { type Metadata = (); } impl Pointee for [u8] { type Metadata = usize; } // ... impl Pointee for Wrapper<u8> { type Metadata = (); } impl Pointee for Wrapper<[u8]> { type Metadata = usize; } // ... // This impl is only selected if `T` is a type parameter or unnormalizable projection or opaque type. fallback impl<T: ?Sized> Pointee for Wrapper<T> where Wrapper<T>: Sized { type Metadata = (); } // This impl is only selected if `T` is a type parameter or unnormalizable projection or opaque type. fallback impl<T /*: Sized */> Pointee for T { type Metadata = (); } ``` to this: ```rust // after impl Pointee for u8 { type Metadata = (); } impl Pointee for [u8] { type Metadata = usize; } // ... impl<T: ?Sized> Pointee for Wrapper<T> { // in the old solver this will instead project to the "deep" tail directly, // e.g. `Wrapper<Wrapper<T>>::Metadata = T::Metadata` type Metadata = <T as Pointee>::Metadata; } // ... // This impl is only selected if `T` is a type parameter or unnormalizable projection or opaque type. fallback impl<T /*: Sized */> Pointee for T { type Metadata = (); } ``` |
||
---|---|---|
.. | ||
src | ||
Cargo.toml | ||
messages.ftl | ||
README.md |
The codegen
crate contains the code to convert from MIR into LLVM IR,
and then from LLVM IR into machine code. In general it contains code
that runs towards the end of the compilation process.
For more information about how codegen works, see the rustc dev guide.