From abf73a6aebbe505694392736e543502c240841db Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Mon, 29 Apr 2019 02:55:43 +0200 Subject: [PATCH 1/2] Support ZSTs in DispatchFromDyn --- src/librustc_typeck/coherence/builtin.rs | 15 +++--- src/test/run-pass/dispatch_from_dyn_zst.rs | 49 +++++++++++++++++++ .../ui/invalid_dispatch_from_dyn_impls.stderr | 2 +- 3 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 src/test/run-pass/dispatch_from_dyn_zst.rs 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(Box, ()); +impl DispatchFromDyn> for WithUnit + where T: Unsize {} + +struct WithPhantom(Box, PhantomData<()>); +impl DispatchFromDyn> for WithPhantom + where T: Unsize {} + +struct WithNever(Box, !); +impl DispatchFromDyn> for WithNever + where T: Unsize {} + +struct WithZst(Box, Zst); +impl DispatchFromDyn> for WithZst + where T: Unsize {} + +struct WithNestedZst(Box, NestedZst); +impl DispatchFromDyn> for WithNestedZst + where T: Unsize {} + + +struct Generic(Box, A); +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn>> + for Generic> + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} + + +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 DispatchFromDyn> for WrapperWithExtraField From 1b679e74f050bc3ff40452e4d4c82d3fc4b03cf4 Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Tue, 30 Apr 2019 14:38:17 +0200 Subject: [PATCH 2/2] Only allow ZSTs with 1 byte alignment --- src/librustc_typeck/coherence/builtin.rs | 6 +++--- src/test/ui/invalid_dispatch_from_dyn_impls.rs | 9 +++++++++ .../ui/invalid_dispatch_from_dyn_impls.stderr | 15 +++++++++++++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index dc5b461ac14..1be0248727d 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -227,8 +227,8 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>( 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 + if layout.is_zst() && layout.details.align.abi.bytes() == 1 { + // ignore ZST fields with alignment of 1 byte return None; } } @@ -238,7 +238,7 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>( create_err( "the trait `DispatchFromDyn` may only be implemented \ for structs containing the field being coerced, \ - ZST 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/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, {} //~^^^ ERROR [E0378] +#[repr(align(64))] +struct OverAlignedZst; +struct OverAligned(Box, OverAlignedZst); + +impl DispatchFromDyn> for OverAligned + where + T: Unsize, +{} //~^^^ 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 624f35d062c..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, ZST 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 DispatchFromDyn> for WrapperWithExtraField @@ -36,6 +36,17 @@ LL | | T: Unsize, 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 DispatchFromDyn> for OverAligned +LL | | where +LL | | T: Unsize, +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`.