@@ -294,17 +294,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
294294
295295 /// Unwrap types that are guaranteed a null-pointer-optimization
296296 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`.
304- return Ok ( layout) ;
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 ADT, so definitely no NPO.
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 {
315+ return Ok ( layout) ; // no NPO
305316 }
317+ } else {
318+ return Ok ( layout) ; // no NPO
306319 } ;
307- let inner = self . layout_of ( inner ) ? ;
320+
308321 // Check if the inner type is one of the NPO-guaranteed ones.
309322 // For that we first unpeel transparent *structs* (but not unions).
310323 let is_npo = |def : AdtDef < ' tcx > | {
0 commit comments