diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 860fa526a1b91..e9ff8aa029675 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -250,11 +250,14 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let needs_drop_copy = || { packed && { let ty = variant.fields.last().unwrap().ty; - let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx) + fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx) + .map(|ty| ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))) .unwrap_or_else(|| { - span_bug!(item.span, "inference variables in {:?}", ty) - }); - ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id)) + fcx_tcx.sess.delay_span_bug( + item.span, &format!("inference variables in {:?}", ty)); + // Just treat unresolved type expression as if it needs drop. + true + }) } }; let all_sized = diff --git a/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs b/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs new file mode 100644 index 0000000000000..d0167c8c268cf --- /dev/null +++ b/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs @@ -0,0 +1,31 @@ +// rust-lang/rust#58158: We have special-case code to deal with case +// when a type is both packed and needs drop glue, (we move the fields +// out of their potentially unaligned locations before dropping them, +// which requires they be Sized; see PR #44884). +// +// So, we need to check if a given type needs drop-glue. That requires +// that we actually know that the concrete type, and we guard against +// the type having unknown parts (i.e. type variables) by ICE'ing in +// that scenario. +// +// But in a case where we have a projection (`Type as Trait::Assoc`) +// where `Type` does not actually implement `Trait`, we of course +// cannot have a concrete type, because there is no impl to look up +// the concrete type for the associated type `Assoc`. +// +// So, this test is just making sure that in such a case that we do +// not immediately ICE, and instead allow the underlying type error to +// surface. + +pub struct Matrix(S); +pub struct DefaultAllocator; + +pub trait Allocator { type Buffer; } + +// impl Allocator for DefaultAllocator { type Buffer = (); } + +#[repr(packed)] +struct Foo(Matrix<::Buffer>); +//~^ ERROR the trait bound `DefaultAllocator: Allocator` is not satisfied + +fn main() { } diff --git a/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr b/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr new file mode 100644 index 0000000000000..e460cdcd3f3e5 --- /dev/null +++ b/src/test/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `DefaultAllocator: Allocator` is not satisfied + --> $DIR/wf-packed-on-proj-of-type-as-unimpl-trait.rs:28:12 + | +LL | struct Foo(Matrix<::Buffer>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Allocator` is not implemented for `DefaultAllocator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.