diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 7349c520c2407..99b2f3e59feb6 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1472,11 +1472,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::StructInitializerSized => { err.note("structs must have a statically known size to be initialized"); } - ObligationCauseCode::FieldSized(ref item) => { + ObligationCauseCode::FieldSized { adt_kind: ref item, last } => { match *item { AdtKind::Struct => { - err.note("only the last field of a struct may have a dynamically \ - sized type"); + if last { + err.note("the last field of a packed struct may only have a \ + dynamically sized type if it does not need drop to be run"); + } else { + err.note("only the last field of a struct may have a dynamically \ + sized type"); + } } AdtKind::Union => { err.note("no field of a union may have a dynamically sized type"); diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 0290f2e3b13f0..08434b5f24ef9 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -192,8 +192,8 @@ pub enum ObligationCauseCode<'tcx> { /// [T,..n] --> T must be Copy RepeatVec, - /// Types of fields (other than the last) in a struct must be sized. - FieldSized(AdtKind), + /// Types of fields (other than the last, except for packed structs) in a struct must be sized. + FieldSized { adt_kind: AdtKind, last: bool }, /// Constant expressions must be sized. ConstSized, diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 39e358803cbe8..544e3f03c03b1 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -206,7 +206,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::SizedReturnType => Some(super::SizedReturnType), super::SizedYieldType => Some(super::SizedYieldType), super::RepeatVec => Some(super::RepeatVec), - super::FieldSized(item) => Some(super::FieldSized(item)), + super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }), super::ConstSized => Some(super::ConstSized), super::SharedStatic => Some(super::SharedStatic), super::BuiltinDerivedObligation(ref cause) => { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 38743cc9cf65f..4b609779540f0 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -258,25 +258,35 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id)) } }; - let unsized_len = if + let all_sized = all_sized || variant.fields.is_empty() || - needs_drop_copy() - { + needs_drop_copy(); + let unsized_len = if all_sized { 0 } else { 1 }; - for field in &variant.fields[..variant.fields.len() - unsized_len] { + for (idx, field) in variant.fields[..variant.fields.len() - unsized_len] + .iter() + .enumerate() + { + let last = idx == variant.fields.len() - 1; fcx.register_bound( field.ty, fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new(field.span, - fcx.body_id, - traits::FieldSized(match item.node.adt_kind() { - Some(i) => i, - None => bug!(), - }))); + traits::ObligationCause::new( + field.span, + fcx.body_id, + traits::FieldSized { + adt_kind: match item.node.adt_kind() { + Some(i) => i, + None => bug!(), + }, + last + } + ) + ); } // All field types must be well-formed. diff --git a/src/test/ui/issues/issue-27060-2.stderr b/src/test/ui/issues/issue-27060-2.stderr index ed9db2ea55ed9..c9a29ac2199c0 100644 --- a/src/test/ui/issues/issue-27060-2.stderr +++ b/src/test/ui/issues/issue-27060-2.stderr @@ -7,7 +7,7 @@ LL | data: T, //~ ERROR the size for values of type = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit = help: consider adding a `where T: std::marker::Sized` bound - = note: only the last field of a struct may have a dynamically sized type + = note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run error: aborting due to previous error