diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-06-23 19:39:58 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-23 19:39:58 +0200 |
| commit | cea5ae00d2eebaa91124396b074317a13d8bc9a3 (patch) | |
| tree | 724e8a8d96cdc7e0d1d30cd1360f8bd5177775f4 /compiler/rustc_ty_utils/src | |
| parent | afe337d2f1f87a307f502e263758e753c326ac1d (diff) | |
| parent | 32f83e18ab1891482873eea6e4337d610393c0a5 (diff) | |
| download | rust-cea5ae00d2eebaa91124396b074317a13d8bc9a3.tar.gz rust-cea5ae00d2eebaa91124396b074317a13d8bc9a3.zip | |
Rollup merge of #112810 - compiler-errors:dont-ice-on-bad-layout, r=wesleywiser
Don't ICE on unnormalized struct tail in layout computation 1. We try to compute a `SizeSkeleton` even if a layout error occurs, but we really only need to do this if we get `LayoutError::Unknown`, since that means our type is too polymorphic to actually compute the full layout. If we have other errors, like `LayoutError::NormalizationError` or `LayoutError::Cycle`, then we can't really make any progress, since this represents an actual error. 2. Avoid using `normalize_erasing_regions` and `struct_tail_erasing_lifetimes` since those ICE on normalization errors, and since we may call `layout_of` in HIR typeck, we don't know for certain that we're on the happy path. Fixes #112736
Diffstat (limited to 'compiler/rustc_ty_utils/src')
| -rw-r--r-- | compiler/rustc_ty_utils/src/layout.rs | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index f48bba24132..c8c2c8286b0 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -145,17 +145,35 @@ fn layout_of_uncached<'tcx>( return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); } - let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); - let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() // Projection eagerly bails out when the pointee references errors, // fall back to structurally deducing metadata. && !pointee.references_error() { - let metadata_ty = tcx.normalize_erasing_regions( + let pointee_metadata = tcx.mk_projection(metadata_def_id, [pointee]); + let metadata_ty = match tcx.try_normalize_erasing_regions( param_env, - tcx.mk_projection(metadata_def_id, [pointee]), - ); + pointee_metadata, + ) { + Ok(metadata_ty) => metadata_ty, + Err(mut err) => { + // Usually `<Ty as Pointee>::Metadata` can't be normalized because + // its struct tail cannot be normalized either, so try to get a + // more descriptive layout error here, which will lead to less confusing + // diagnostics. + match tcx.try_normalize_erasing_regions( + param_env, + tcx.struct_tail_without_normalization(pointee), + ) { + Ok(_) => {}, + Err(better_err) => { + err = better_err; + } + } + return Err(LayoutError::NormalizationFailure(pointee, err)); + }, + }; + let metadata_layout = cx.layout_of(metadata_ty)?; // If the metadata is a 1-zst, then the pointer is thin. if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 { @@ -163,10 +181,13 @@ fn layout_of_uncached<'tcx>( } let Abi::Scalar(metadata) = metadata_layout.abi else { - return Err(LayoutError::Unknown(unsized_part)); + return Err(LayoutError::Unknown(pointee)); }; + metadata } else { + let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); + match unsized_part.kind() { ty::Foreign(..) => { return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); @@ -178,7 +199,7 @@ fn layout_of_uncached<'tcx>( vtable } _ => { - return Err(LayoutError::Unknown(unsized_part)); + return Err(LayoutError::Unknown(pointee)); } } }; |
