about summary refs log tree commit diff
path: root/compiler/rustc_ty_utils/src
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-06-23 19:39:58 +0200
committerGitHub <noreply@github.com>2023-06-23 19:39:58 +0200
commitcea5ae00d2eebaa91124396b074317a13d8bc9a3 (patch)
tree724e8a8d96cdc7e0d1d30cd1360f8bd5177775f4 /compiler/rustc_ty_utils/src
parentafe337d2f1f87a307f502e263758e753c326ac1d (diff)
parent32f83e18ab1891482873eea6e4337d610393c0a5 (diff)
downloadrust-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.rs35
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));
                     }
                 }
             };