Fix unsize coerce for structs containing PhantomData like Unique

This commit is contained in:
bjorn3 2018-09-16 14:49:45 +02:00
parent 73248114ea
commit 19eb4194b2
3 changed files with 27 additions and 0 deletions

View File

@ -12,6 +12,7 @@ pub trait Unsize<T: ?Sized> {}
pub trait CoerceUnsized<T> {}
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
#[lang = "copy"]
@ -169,6 +170,9 @@ impl<T: ?Sized> PartialEq for *const T {
}
}
#[lang = "phantom_data"]
pub struct PhantomData<T: ?Sized>;
#[lang = "fn_once"]
#[rustc_paren_sugar]
pub trait FnOnce<Args> {

View File

@ -102,6 +102,13 @@ macro_rules! assert_eq {
}
}
struct Unique<T: ?Sized> {
pointer: *const T,
_marker: PhantomData<T>,
}
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
fn main() {
unsafe {
let hello: &[u8] = b"Hello\0" as &[u8; 6];
@ -133,6 +140,11 @@ fn main() {
assert!(!intrinsics::needs_drop::<u8>());
assert!(intrinsics::needs_drop::<NoisyDrop>());
Unique {
pointer: 0 as *const &str,
_marker: PhantomData,
} as Unique<dyn SomeTrait>;
}
let _ = NoisyDrop {

View File

@ -259,6 +259,17 @@ impl<'tcx> CValue<'tcx> {
for idx in 0..field_count {
let field_dest = dest.place_field(fx, mir::Field::new(idx));
let field_src = self.value_field(fx, mir::Field::new(idx));
if field_src.layout().ty.is_phantom_data() {
// Ignore PhantomData so for example `Unique<()>` can coerce to `Unique<Debug>`
//
// ```rust
// struct Unique<T: ?Sized> {
// pointer: NonZero<*const T>,
// _marker: PhantomData<T>,
// }
// ```
continue;
}
if field_src.layout().ty != field_dest.layout().ty {
assert!(!found_unsize_field);
found_unsize_field = true;