@@ -294,17 +294,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
294
294
295
295
/// Unwrap types that are guaranteed a null-pointer-optimization
296
296
fn unfold_npo ( & self , layout : TyAndLayout < ' tcx > ) -> InterpResult < ' tcx , TyAndLayout < ' tcx > > {
297
- // Check if this is `Option` wrapping some type.
298
- let inner = match layout. ty . kind ( ) {
299
- ty:: Adt ( def, args) if self . tcx . is_diagnostic_item ( sym:: Option , def. did ( ) ) => {
300
- args[ 0 ] . as_type ( ) . unwrap ( )
301
- }
302
- _ => {
303
- // Not an `Option`.
297
+ // Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and
298
+ // another type.
299
+ let ty:: Adt ( def, args) = layout. ty . kind ( ) else {
300
+ // Not an `Option` or Result.
301
+ return Ok ( layout) ;
302
+ } ;
303
+ let inner = if self . tcx . is_diagnostic_item ( sym:: Option , def. did ( ) ) {
304
+ // The wrapped type is the only arg.
305
+ self . layout_of ( args[ 0 ] . as_type ( ) . unwrap ( ) ) ?
306
+ } else if self . tcx . is_diagnostic_item ( sym:: Result , def. did ( ) ) {
307
+ // We want to extract which (if any) of the args is not a 1-ZST.
308
+ let lhs = self . layout_of ( args[ 0 ] . as_type ( ) . unwrap ( ) ) ?;
309
+ let rhs = self . layout_of ( args[ 1 ] . as_type ( ) . unwrap ( ) ) ?;
310
+ if lhs. is_1zst ( ) {
311
+ rhs
312
+ } else if rhs. is_1zst ( ) {
313
+ lhs
314
+ } else {
304
315
return Ok ( layout) ;
305
316
}
317
+ } else {
318
+ return Ok ( layout) ;
306
319
} ;
307
- let inner = self . layout_of ( inner ) ? ;
320
+
308
321
// Check if the inner type is one of the NPO-guaranteed ones.
309
322
// For that we first unpeel transparent *structs* (but not unions).
310
323
let is_npo = |def : AdtDef < ' tcx > | {
0 commit comments