diff options
Diffstat (limited to 'compiler/rustc_ty_utils/src/layout.rs')
| -rw-r--r-- | compiler/rustc_ty_utils/src/layout.rs | 117 |
1 files changed, 80 insertions, 37 deletions
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 17be0bd0ab9..ce8dc3a2515 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -104,14 +104,12 @@ fn map_error<'tcx>( // This is sometimes not a compile error if there are trivially false where clauses. // See `tests/ui/layout/trivial-bounds-sized.rs` for an example. assert!(field.layout.is_unsized(), "invalid layout error {err:#?}"); - if !field.ty.is_sized(cx.tcx(), cx.typing_env) { - let guar = cx.tcx().dcx().delayed_bug(format!( + if cx.typing_env.param_env.caller_bounds().is_empty() { + cx.tcx().dcx().delayed_bug(format!( "encountered unexpected unsized field in layout of {ty:?}: {field:#?}" )); - LayoutError::ReferencesError(guar) - } else { - LayoutError::Unknown(ty) } + LayoutError::Unknown(ty) } LayoutCalculatorError::EmptyUnion => { // This is always a compile error. @@ -146,6 +144,35 @@ fn univariant_uninterned<'tcx>( cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err)) } +fn extract_const_value<'tcx>( + const_: ty::Const<'tcx>, + ty: Ty<'tcx>, + cx: &LayoutCx<'tcx>, +) -> Result<ty::Value<'tcx>, &'tcx LayoutError<'tcx>> { + match const_.kind() { + ty::ConstKind::Value(cv) => Ok(cv), + ty::ConstKind::Error(guar) => { + return Err(error(cx, LayoutError::ReferencesError(guar))); + } + ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => { + if !const_.has_param() { + bug!("no generic type found in the type: {ty:?}"); + } + return Err(error(cx, LayoutError::TooGeneric(ty))); + } + ty::ConstKind::Unevaluated(_) => { + if !const_.has_param() { + return Err(error(cx, LayoutError::Unknown(ty))); + } else { + return Err(error(cx, LayoutError::TooGeneric(ty))); + } + } + ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { + bug!("unexpected type: {ty:?}"); + } + } +} + fn layout_of_uncached<'tcx>( cx: &LayoutCx<'tcx>, ty: Ty<'tcx>, @@ -182,12 +209,12 @@ fn layout_of_uncached<'tcx>( &mut layout.backend_repr { if let Some(start) = start { - scalar.valid_range_mut().start = start + scalar.valid_range_mut().start = extract_const_value(start, ty, cx)? .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; } if let Some(end) = end { - let mut end = end + let mut end = extract_const_value(end, ty, cx)? .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; if !include_end { @@ -213,14 +240,20 @@ fn layout_of_uncached<'tcx>( } // Basic scalars. - ty::Bool => tcx.mk_layout(LayoutData::scalar(cx, Scalar::Initialized { - value: Int(I8, false), - valid_range: WrappingRange { start: 0, end: 1 }, - })), - ty::Char => tcx.mk_layout(LayoutData::scalar(cx, Scalar::Initialized { - value: Int(I32, false), - valid_range: WrappingRange { start: 0, end: 0x10FFFF }, - })), + ty::Bool => tcx.mk_layout(LayoutData::scalar( + cx, + Scalar::Initialized { + value: Int(I8, false), + valid_range: WrappingRange { start: 0, end: 1 }, + }, + )), + ty::Char => tcx.mk_layout(LayoutData::scalar( + cx, + Scalar::Initialized { + value: Int(I32, false), + valid_range: WrappingRange { start: 0, end: 0x10FFFF }, + }, + )), ty::Int(ity) => scalar(Int(abi::Integer::from_int_ty(dl, ity), true)), ty::Uint(ity) => scalar(Int(abi::Integer::from_uint_ty(dl, ity), false)), ty::Float(fty) => scalar(Float(abi::Float::from_float_ty(fty))), @@ -319,17 +352,11 @@ fn layout_of_uncached<'tcx>( } // Arrays and slices. - ty::Array(element, mut count) => { - if count.has_aliases() { - count = tcx.normalize_erasing_regions(cx.typing_env, count); - if count.has_aliases() { - return Err(error(cx, LayoutError::Unknown(ty))); - } - } - - let count = count + ty::Array(element, count) => { + let count = extract_const_value(count, ty, cx)? .try_to_target_usize(tcx) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; + let element = cx.layout_of(element)?; let size = element .size @@ -530,10 +557,13 @@ fn layout_of_uncached<'tcx>( // Non-power-of-two vectors have padding up to the next power-of-two. // If we're a packed repr, remove the padding while keeping the alignment as close // to a vector as possible. - (BackendRepr::Memory { sized: true }, AbiAndPrefAlign { - abi: Align::max_for_offset(size), - pref: dl.vector_align(size).pref, - }) + ( + BackendRepr::Memory { sized: true }, + AbiAndPrefAlign { + abi: Align::max_for_offset(size), + pref: dl.vector_align(size).pref, + }, + ) } else { (BackendRepr::Vector { element: e_abi, count: e_len }, dl.vector_align(size)) }; @@ -687,6 +717,9 @@ fn layout_of_uncached<'tcx>( // Types with no meaningful known layout. ty::Alias(..) => { + if ty.has_param() { + return Err(error(cx, LayoutError::TooGeneric(ty))); + } // NOTE(eddyb) `layout_of` query should've normalized these away, // if that was possible, so there's no reason to try again here. return Err(error(cx, LayoutError::Unknown(ty))); @@ -696,7 +729,11 @@ fn layout_of_uncached<'tcx>( bug!("Layout::compute: unexpected type `{}`", ty) } - ty::Placeholder(..) | ty::Param(_) => { + ty::Param(_) => { + return Err(error(cx, LayoutError::TooGeneric(ty))); + } + + ty::Placeholder(..) => { return Err(error(cx, LayoutError::Unknown(ty))); } }) @@ -1151,10 +1188,13 @@ fn variant_info_for_adt<'tcx>( }) .collect(); - (variant_infos, match tag_encoding { - TagEncoding::Direct => Some(tag.size(cx)), - _ => None, - }) + ( + variant_infos, + match tag_encoding { + TagEncoding::Direct => Some(tag.size(cx)), + _ => None, + }, + ) } } } @@ -1274,8 +1314,11 @@ fn variant_info_for_coroutine<'tcx>( let end_states: Vec<_> = end_states.collect(); variant_infos.extend(end_states); - (variant_infos, match tag_encoding { - TagEncoding::Direct => Some(tag.size(cx)), - _ => None, - }) + ( + variant_infos, + match tag_encoding { + TagEncoding::Direct => Some(tag.size(cx)), + _ => None, + }, + ) } |
