1
Fork 0

Don't ICE on unnormalized struct tail in layout computation

This commit is contained in:
Michael Goulet 2023-06-19 19:57:44 +00:00
parent 3b2073f076
commit dd620aa73a
6 changed files with 65 additions and 12 deletions

View file

@ -318,7 +318,13 @@ impl<'tcx> SizeSkeleton<'tcx> {
Ok(layout) => { Ok(layout) => {
return Ok(SizeSkeleton::Known(layout.size)); return Ok(SizeSkeleton::Known(layout.size));
} }
Err(err) => err, Err(err @ LayoutError::Unknown(_)) => err,
// We can't extract SizeSkeleton info from other layout errors
Err(
e @ LayoutError::Cycle
| e @ LayoutError::SizeOverflow(_)
| e @ LayoutError::NormalizationFailure(..),
) => return Err(e),
}; };
match *ty.kind() { match *ty.kind() {

View file

@ -145,17 +145,20 @@ fn layout_of_uncached<'tcx>(
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); 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() let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
// Projection eagerly bails out when the pointee references errors, // Projection eagerly bails out when the pointee references errors,
// fall back to structurally deducing metadata. // fall back to structurally deducing metadata.
&& !pointee.references_error() && !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, param_env,
tcx.mk_projection(metadata_def_id, [pointee]), pointee_metadata,
); ) {
Ok(metadata_ty) => metadata_ty,
Err(err) => return Err(LayoutError::NormalizationFailure(pointee, err)),
};
let metadata_layout = cx.layout_of(metadata_ty)?; let metadata_layout = cx.layout_of(metadata_ty)?;
// If the metadata is a 1-zst, then the pointer is thin. // If the metadata is a 1-zst, then the pointer is thin.
if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 { if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 {
@ -163,10 +166,13 @@ fn layout_of_uncached<'tcx>(
} }
let Abi::Scalar(metadata) = metadata_layout.abi else { let Abi::Scalar(metadata) = metadata_layout.abi else {
return Err(LayoutError::Unknown(unsized_part)); return Err(LayoutError::Unknown(pointee));
}; };
metadata metadata
} else { } else {
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
match unsized_part.kind() { match unsized_part.kind() {
ty::Foreign(..) => { ty::Foreign(..) => {
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
@ -178,7 +184,7 @@ fn layout_of_uncached<'tcx>(
vtable vtable
} }
_ => { _ => {
return Err(LayoutError::Unknown(unsized_part)); return Err(LayoutError::Unknown(pointee));
} }
} }
}; };

View file

@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
LL | unsafe { std::mem::transmute(v) } LL | unsafe { std::mem::transmute(v) }
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
| |
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture) = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
= note: target type: `[[[u32; 9999999]; 777777777]; 239]` (59484438436515561504 bits) = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
error: aborting due to previous error error: aborting due to previous error

View file

@ -43,8 +43,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
LL | std::mem::transmute(v) LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
| |
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture) = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[[u32; 9999999]; 777777777]; 8888888]` are too big for the current architecture) = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
error: aborting due to 6 previous errors error: aborting due to 6 previous errors

View file

@ -0,0 +1,22 @@
trait Trait {
type RefTarget;
}
impl Trait for ()
where
Missing: Trait,
//~^ ERROR cannot find type `Missing` in this scope
{
type RefTarget = ();
}
struct Other {
data: <() as Trait>::RefTarget,
}
fn main() {
unsafe {
std::mem::transmute::<Option<()>, Option<&Other>>(None);
//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
}
}

View file

@ -0,0 +1,19 @@
error[E0412]: cannot find type `Missing` in this scope
--> $DIR/cannot-transmute-unnormalizable-type.rs:7:5
|
LL | Missing: Trait,
| ^^^^^^^ not found in this scope
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/cannot-transmute-unnormalizable-type.rs:19:9
|
LL | std::mem::transmute::<Option<()>, Option<&Other>>(None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: source type: `Option<()>` (8 bits)
= note: target type: `Option<&Other>` (unable to determine layout for `Other` because `<Other as Pointee>::Metadata` cannot be normalized)
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0412, E0512.
For more information about an error, try `rustc --explain E0412`.