Skip to content

Commit cea5ae0

Browse files
authoredJun 23, 2023
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
2 parents afe337d + 32f83e1 commit cea5ae0

File tree

6 files changed

+80
-12
lines changed

6 files changed

+80
-12
lines changed
 

‎compiler/rustc_middle/src/ty/layout.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,13 @@ impl<'tcx> SizeSkeleton<'tcx> {
318318
Ok(layout) => {
319319
return Ok(SizeSkeleton::Known(layout.size));
320320
}
321-
Err(err) => err,
321+
Err(err @ LayoutError::Unknown(_)) => err,
322+
// We can't extract SizeSkeleton info from other layout errors
323+
Err(
324+
e @ LayoutError::Cycle
325+
| e @ LayoutError::SizeOverflow(_)
326+
| e @ LayoutError::NormalizationFailure(..),
327+
) => return Err(e),
322328
};
323329

324330
match *ty.kind() {

‎compiler/rustc_ty_utils/src/layout.rs

+28-7
Original file line numberDiff line numberDiff line change
@@ -145,28 +145,49 @@ fn layout_of_uncached<'tcx>(
145145
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
146146
}
147147

148-
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
149-
150148
let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
151149
// Projection eagerly bails out when the pointee references errors,
152150
// fall back to structurally deducing metadata.
153151
&& !pointee.references_error()
154152
{
155-
let metadata_ty = tcx.normalize_erasing_regions(
153+
let pointee_metadata = tcx.mk_projection(metadata_def_id, [pointee]);
154+
let metadata_ty = match tcx.try_normalize_erasing_regions(
156155
param_env,
157-
tcx.mk_projection(metadata_def_id, [pointee]),
158-
);
156+
pointee_metadata,
157+
) {
158+
Ok(metadata_ty) => metadata_ty,
159+
Err(mut err) => {
160+
// Usually `<Ty as Pointee>::Metadata` can't be normalized because
161+
// its struct tail cannot be normalized either, so try to get a
162+
// more descriptive layout error here, which will lead to less confusing
163+
// diagnostics.
164+
match tcx.try_normalize_erasing_regions(
165+
param_env,
166+
tcx.struct_tail_without_normalization(pointee),
167+
) {
168+
Ok(_) => {},
169+
Err(better_err) => {
170+
err = better_err;
171+
}
172+
}
173+
return Err(LayoutError::NormalizationFailure(pointee, err));
174+
},
175+
};
176+
159177
let metadata_layout = cx.layout_of(metadata_ty)?;
160178
// If the metadata is a 1-zst, then the pointer is thin.
161179
if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 {
162180
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
163181
}
164182

165183
let Abi::Scalar(metadata) = metadata_layout.abi else {
166-
return Err(LayoutError::Unknown(unsized_part));
184+
return Err(LayoutError::Unknown(pointee));
167185
};
186+
168187
metadata
169188
} else {
189+
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
190+
170191
match unsized_part.kind() {
171192
ty::Foreign(..) => {
172193
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
@@ -178,7 +199,7 @@ fn layout_of_uncached<'tcx>(
178199
vtable
179200
}
180201
_ => {
181-
return Err(LayoutError::Unknown(unsized_part));
202+
return Err(LayoutError::Unknown(pointee));
182203
}
183204
}
184205
};

‎tests/ui/const-generics/issue-112505-overflow.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
44
LL | unsafe { std::mem::transmute(v) }
55
| ^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture)
8-
= note: target type: `[[[u32; 9999999]; 777777777]; 239]` (59484438436515561504 bits)
7+
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
8+
= note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
99

1010
error: aborting due to previous error
1111

‎tests/ui/const-generics/transmute-fail.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
4343
LL | std::mem::transmute(v)
4444
| ^^^^^^^^^^^^^^^^^^^
4545
|
46-
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture)
47-
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[[u32; 9999999]; 777777777]; 8888888]` are too big for the current architecture)
46+
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
47+
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
4848

4949
error: aborting due to 6 previous errors
5050

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
trait Trait {
2+
type RefTarget;
3+
}
4+
5+
impl Trait for ()
6+
where
7+
Missing: Trait,
8+
//~^ ERROR cannot find type `Missing` in this scope
9+
{
10+
type RefTarget = ();
11+
}
12+
13+
struct Other {
14+
data: <() as Trait>::RefTarget,
15+
}
16+
17+
fn main() {
18+
unsafe {
19+
std::mem::transmute::<Option<()>, Option<&Other>>(None);
20+
//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0412]: cannot find type `Missing` in this scope
2+
--> $DIR/cannot-transmute-unnormalizable-type.rs:7:5
3+
|
4+
LL | Missing: Trait,
5+
| ^^^^^^^ not found in this scope
6+
7+
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
8+
--> $DIR/cannot-transmute-unnormalizable-type.rs:19:9
9+
|
10+
LL | std::mem::transmute::<Option<()>, Option<&Other>>(None);
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
|
13+
= note: source type: `Option<()>` (8 bits)
14+
= note: target type: `Option<&Other>` (unable to determine layout for `Other` because `<() as Trait>::RefTarget` cannot be normalized)
15+
16+
error: aborting due to 2 previous errors
17+
18+
Some errors have detailed explanations: E0412, E0512.
19+
For more information about an error, try `rustc --explain E0412`.

0 commit comments

Comments
 (0)