diff options
| -rw-r--r-- | src/librustc_typeck/coherence/builtin.rs | 15 | ||||
| -rw-r--r-- | src/test/run-pass/dispatch_from_dyn_zst.rs | 49 | ||||
| -rw-r--r-- | src/test/ui/invalid_dispatch_from_dyn_impls.stderr | 2 |
3 files changed, 59 insertions, 7 deletions
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index c3b08569d2f..dc5b461ac14 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -223,19 +223,22 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>( let fields = &def_a.non_enum_variant().fields; let coerced_fields = fields.iter().filter_map(|field| { - if tcx.type_of(field.did).is_phantom_data() { - // ignore PhantomData fields - return None - } - let ty_a = field.ty(tcx, substs_a); let ty_b = field.ty(tcx, substs_b); + + if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) { + if layout.is_zst() { + // ignore ZST fields + return None; + } + } + if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) { if ok.obligations.is_empty() { create_err( "the trait `DispatchFromDyn` may only be implemented \ for structs containing the field being coerced, \ - `PhantomData` fields, and nothing else" + ZST fields, and nothing else" ).note( &format!( "extra field `{}` of type `{}` is not allowed", diff --git a/src/test/run-pass/dispatch_from_dyn_zst.rs b/src/test/run-pass/dispatch_from_dyn_zst.rs new file mode 100644 index 00000000000..a2181336e00 --- /dev/null +++ b/src/test/run-pass/dispatch_from_dyn_zst.rs @@ -0,0 +1,49 @@ +#![feature(unsize, dispatch_from_dyn, never_type)] + +#![allow(dead_code)] + +use std::{ + ops::DispatchFromDyn, + marker::{Unsize, PhantomData}, +}; + +struct Zst; +struct NestedZst(PhantomData<()>, Zst); + + +struct WithUnit<T: ?Sized>(Box<T>, ()); +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithUnit<U>> for WithUnit<T> + where T: Unsize<U> {} + +struct WithPhantom<T: ?Sized>(Box<T>, PhantomData<()>); +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithPhantom<U>> for WithPhantom<T> + where T: Unsize<U> {} + +struct WithNever<T: ?Sized>(Box<T>, !); +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithNever<U>> for WithNever<T> + where T: Unsize<U> {} + +struct WithZst<T: ?Sized>(Box<T>, Zst); +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithZst<U>> for WithZst<T> + where T: Unsize<U> {} + +struct WithNestedZst<T: ?Sized>(Box<T>, NestedZst); +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithNestedZst<U>> for WithNestedZst<T> + where T: Unsize<U> {} + + +struct Generic<T: ?Sized, A>(Box<T>, A); +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, ()>> for Generic<T, ()> + where T: Unsize<U> {} +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, PhantomData<()>>> + for Generic<T, PhantomData<()>> + where T: Unsize<U> {} +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, !>> for Generic<T, !> + where T: Unsize<U> {} +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, Zst>> for Generic<T, Zst> + where T: Unsize<U> {} +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, NestedZst>> for Generic<T, NestedZst> + where T: Unsize<U> {} + + +fn main() {} diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr index bd016466300..624f35d062c 100644 --- a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr +++ b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr @@ -1,4 +1,4 @@ -error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else +error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields, and nothing else --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1 | LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T> |
