Update the interpreter to handle the new cases
This commit is contained in:
parent
f4b060e452
commit
b710404f3b
1 changed files with 23 additions and 10 deletions
|
@ -294,17 +294,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
|
|
||||||
/// Unwrap types that are guaranteed a null-pointer-optimization
|
/// Unwrap types that are guaranteed a null-pointer-optimization
|
||||||
fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
|
fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
|
||||||
// Check if this is `Option` wrapping some type.
|
// Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and
|
||||||
let inner = match layout.ty.kind() {
|
// another type.
|
||||||
ty::Adt(def, args) if self.tcx.is_diagnostic_item(sym::Option, def.did()) => {
|
let ty::Adt(def, args) = layout.ty.kind() else {
|
||||||
args[0].as_type().unwrap()
|
// Not an ADT, so definitely no NPO.
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// Not an `Option`.
|
|
||||||
return Ok(layout);
|
return Ok(layout);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let inner = self.layout_of(inner)?;
|
let inner = if self.tcx.is_diagnostic_item(sym::Option, def.did()) {
|
||||||
|
// The wrapped type is the only arg.
|
||||||
|
self.layout_of(args[0].as_type().unwrap())?
|
||||||
|
} else if self.tcx.is_diagnostic_item(sym::Result, def.did()) {
|
||||||
|
// We want to extract which (if any) of the args is not a 1-ZST.
|
||||||
|
let lhs = self.layout_of(args[0].as_type().unwrap())?;
|
||||||
|
let rhs = self.layout_of(args[1].as_type().unwrap())?;
|
||||||
|
if lhs.is_1zst() {
|
||||||
|
rhs
|
||||||
|
} else if rhs.is_1zst() {
|
||||||
|
lhs
|
||||||
|
} else {
|
||||||
|
return Ok(layout); // no NPO
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Ok(layout); // no NPO
|
||||||
|
};
|
||||||
|
|
||||||
// Check if the inner type is one of the NPO-guaranteed ones.
|
// Check if the inner type is one of the NPO-guaranteed ones.
|
||||||
// For that we first unpeel transparent *structs* (but not unions).
|
// For that we first unpeel transparent *structs* (but not unions).
|
||||||
let is_npo = |def: AdtDef<'tcx>| {
|
let is_npo = |def: AdtDef<'tcx>| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue