| //@ check-pass | |
| //@ revisions: old next | |
| //@[next] compile-flags: -Znext-solver | |
| #![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); | |
| // normalize `Wrapper<T>::Metadata` -> `T::Metadata` | |
| fn wrapper_to_tail<T: ?Sized>(ptr: *const T) -> *const Wrapper<T> { | |
| cast_same_meta(ptr) | |
| } | |
| // normalize `Wrapper<T>::Metadata` -> `T::Metadata` -> `()` | |
| fn wrapper_to_unit<T>(ptr: *const ()) -> *const Wrapper<T> { | |
| cast_same_meta(ptr) | |
| } | |
| trait Project { | |
| type Assoc: ?Sized; | |
| } | |
| struct WrapperProject<T: ?Sized + Project>(T::Assoc); | |
| // normalize `WrapperProject<T>::Metadata` -> `T::Assoc::Metadata` | |
| fn wrapper_project_tail<T: ?Sized + Project>(ptr: *const T::Assoc) -> *const WrapperProject<T> { | |
| cast_same_meta(ptr) | |
| } | |
| // normalize `WrapperProject<T>::Metadata` -> `T::Assoc::Metadata` -> `()` | |
| fn wrapper_project_unit<T: ?Sized + Project>(ptr: *const ()) -> *const WrapperProject<T> | |
| where | |
| T::Assoc: Sized, | |
| { | |
| cast_same_meta(ptr) | |
| } | |
| // normalize `<[T] as Pointee>::Metadata` -> `usize`, even if `[T]: Sized` | |
| fn sized_slice<T>(ptr: *const [T]) -> *const str | |
| where | |
| [T]: Sized, | |
| { | |
| cast_same_meta(ptr) | |
| } | |
| fn main() {} |