diff options
Diffstat (limited to 'compiler/rustc_ty_utils/src/layout.rs')
| -rw-r--r-- | compiler/rustc_ty_utils/src/layout.rs | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index dd1f2322c41..4ecb0ea7cd9 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -8,7 +8,9 @@ use rustc_middle::ty::layout::{ IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES, }; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, AdtDef, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{ + self, AdtDef, EarlyBinder, FieldDef, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, +}; use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::sym; use rustc_span::symbol::Symbol; @@ -506,6 +508,40 @@ fn layout_of_uncached<'tcx>( )); } + let err_if_unsized = |field: &FieldDef, err_msg: &str| { + let field_ty = tcx.type_of(field.did); + let is_unsized = tcx + .try_instantiate_and_normalize_erasing_regions(args, cx.param_env, field_ty) + .map(|f| !f.is_sized(tcx, cx.param_env)) + .map_err(|e| { + error( + cx, + LayoutError::NormalizationFailure(field_ty.instantiate_identity(), e), + ) + })?; + + if is_unsized { + cx.tcx.dcx().span_delayed_bug(tcx.def_span(def.did()), err_msg.to_owned()); + Err(error(cx, LayoutError::Unknown(ty))) + } else { + Ok(()) + } + }; + + if def.is_struct() { + if let Some((_, fields_except_last)) = + def.non_enum_variant().fields.raw.split_last() + { + for f in fields_except_last { + err_if_unsized(f, "only the last field of a struct can be unsized")?; + } + } + } else { + for f in def.all_fields() { + err_if_unsized(f, &format!("{}s cannot have unsized fields", def.descr()))?; + } + } + let get_discriminant_type = |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max); |
