diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-05-01 08:29:14 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-05-01 08:29:14 +0200 |
| commit | 604176cc105fda9deebc053d478f0e89bbf5e61b (patch) | |
| tree | e61437dce63d192cc17a34f09c6c1ea9c36b1c47 /src | |
| parent | edb3cf57dcca77f31a019a8453d591c867b14eee (diff) | |
| parent | 1b679e74f050bc3ff40452e4d4c82d3fc4b03cf4 (diff) | |
| download | rust-604176cc105fda9deebc053d478f0e89bbf5e61b.tar.gz rust-604176cc105fda9deebc053d478f0e89bbf5e61b.zip | |
Rollup merge of #60369 - TimDiekmann:dispatch-zst, r=eddyb
Support ZSTs in DispatchFromDyn Allows to use ZSTs with 1 byte alignment in `DispatchFromDyn` implementation. This is required for `Box<T, A: Alloc>` cc #58457
Diffstat (limited to 'src')
| -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.rs | 9 | ||||
| -rw-r--r-- | src/test/ui/invalid_dispatch_from_dyn_impls.stderr | 15 |
4 files changed, 80 insertions, 8 deletions
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index c3b08569d2f..1be0248727d 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() && layout.details.align.abi.bytes() == 1 { + // ignore ZST fields with alignment of 1 byte + 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 with 1 byte alignment, 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.rs b/src/test/ui/invalid_dispatch_from_dyn_impls.rs index c4716893fbc..b7bc766fbe0 100644 --- a/src/test/ui/invalid_dispatch_from_dyn_impls.rs +++ b/src/test/ui/invalid_dispatch_from_dyn_impls.rs @@ -39,4 +39,13 @@ where T: Unsize<U>, {} //~^^^ ERROR [E0378] +#[repr(align(64))] +struct OverAlignedZst; +struct OverAligned<T: ?Sized>(Box<T>, OverAlignedZst); + +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T> + where + T: Unsize<U>, +{} //~^^^ ERROR [E0378] + 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..6d62d4fd071 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 with 1 byte alignment, and nothing else --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1 | LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T> @@ -36,6 +36,17 @@ LL | | T: Unsize<U>, LL | | {} | |__^ -error: aborting due to 4 previous errors +error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else + --> $DIR/invalid_dispatch_from_dyn_impls.rs:46:1 + | +LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T> +LL | | where +LL | | T: Unsize<U>, +LL | | {} + | |__^ + | + = note: extra field `1` of type `OverAlignedZst` is not allowed + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0378`. |
