@@ -393,19 +393,22 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
393393 must_unwind : common:: type_needs_unwind_cleanup ( self . ccx , ty) ,
394394 val : val,
395395 ty : ty,
396- zero : false
396+ fill_on_drop : false ,
397+ skip_dtor : false ,
397398 } ;
398399
399- debug ! ( "schedule_drop_mem({:?}, val={}, ty={})" ,
400+ debug ! ( "schedule_drop_mem({:?}, val={}, ty={}) fill_on_drop={} skip_dtor={} " ,
400401 cleanup_scope,
401402 self . ccx. tn( ) . val_to_string( val) ,
402- ty. repr( self . ccx. tcx( ) ) ) ;
403+ ty. repr( self . ccx. tcx( ) ) ,
404+ drop. fill_on_drop,
405+ drop. skip_dtor) ;
403406
404407 self . schedule_clean ( cleanup_scope, drop as CleanupObj ) ;
405408 }
406409
407- /// Schedules a (deep) drop and zero-ing of `val`, which is a pointer to an instance of `ty`
408- fn schedule_drop_and_zero_mem ( & self ,
410+ /// Schedules a (deep) drop and filling of `val`, which is a pointer to an instance of `ty`
411+ fn schedule_drop_and_fill_mem ( & self ,
409412 cleanup_scope : ScopeId ,
410413 val : ValueRef ,
411414 ty : Ty < ' tcx > ) {
@@ -416,14 +419,48 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
416419 must_unwind : common:: type_needs_unwind_cleanup ( self . ccx , ty) ,
417420 val : val,
418421 ty : ty,
419- zero : true
422+ fill_on_drop : true ,
423+ skip_dtor : false ,
424+ } ;
425+
426+ debug ! ( "schedule_drop_and_fill_mem({:?}, val={}, ty={}, fill_on_drop={}, skip_dtor={})" ,
427+ cleanup_scope,
428+ self . ccx. tn( ) . val_to_string( val) ,
429+ ty. repr( self . ccx. tcx( ) ) ,
430+ drop. fill_on_drop,
431+ drop. skip_dtor) ;
432+
433+ self . schedule_clean ( cleanup_scope, drop as CleanupObj ) ;
434+ }
435+
436+ /// Issue #23611: Schedules a (deep) drop of the contents of
437+ /// `val`, which is a pointer to an instance of struct/enum type
438+ /// `ty`. The scheduled code handles extracting the discriminant
439+ /// and dropping the contents associated with that variant
440+ /// *without* executing any associated drop implementation.
441+ fn schedule_drop_enum_contents ( & self ,
442+ cleanup_scope : ScopeId ,
443+ val : ValueRef ,
444+ ty : Ty < ' tcx > ) {
445+ // `if` below could be "!contents_needs_drop"; skipping drop
446+ // is just an optimization, so sound to be conservative.
447+ if !self . type_needs_drop ( ty) { return ; }
448+
449+ let drop = box DropValue {
450+ is_immediate : false ,
451+ must_unwind : common:: type_needs_unwind_cleanup ( self . ccx , ty) ,
452+ val : val,
453+ ty : ty,
454+ fill_on_drop : false ,
455+ skip_dtor : true ,
420456 } ;
421457
422- debug ! ( "schedule_drop_and_zero_mem ({:?}, val={}, ty={}, zero ={}) " ,
458+ debug ! ( "schedule_drop_enum_contents ({:?}, val={}, ty={}) fill_on_drop ={} skip_dtor={} " ,
423459 cleanup_scope,
424460 self . ccx. tn( ) . val_to_string( val) ,
425461 ty. repr( self . ccx. tcx( ) ) ,
426- true ) ;
462+ drop. fill_on_drop,
463+ drop. skip_dtor) ;
427464
428465 self . schedule_clean ( cleanup_scope, drop as CleanupObj ) ;
429466 }
@@ -440,13 +477,16 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
440477 must_unwind : common:: type_needs_unwind_cleanup ( self . ccx , ty) ,
441478 val : val,
442479 ty : ty,
443- zero : false
480+ fill_on_drop : false ,
481+ skip_dtor : false ,
444482 } ;
445483
446- debug ! ( "schedule_drop_immediate({:?}, val={}, ty={:?})" ,
484+ debug ! ( "schedule_drop_immediate({:?}, val={}, ty={:?}) fill_on_drop={} skip_dtor={} " ,
447485 cleanup_scope,
448486 self . ccx. tn( ) . val_to_string( val) ,
449- ty. repr( self . ccx. tcx( ) ) ) ;
487+ ty. repr( self . ccx. tcx( ) ) ,
488+ drop. fill_on_drop,
489+ drop. skip_dtor) ;
450490
451491 self . schedule_clean ( cleanup_scope, drop as CleanupObj ) ;
452492 }
@@ -987,7 +1027,8 @@ pub struct DropValue<'tcx> {
9871027 must_unwind : bool ,
9881028 val : ValueRef ,
9891029 ty : Ty < ' tcx > ,
990- zero : bool
1030+ fill_on_drop : bool ,
1031+ skip_dtor : bool ,
9911032}
9921033
9931034impl < ' tcx > Cleanup < ' tcx > for DropValue < ' tcx > {
@@ -1007,13 +1048,18 @@ impl<'tcx> Cleanup<'tcx> for DropValue<'tcx> {
10071048 bcx : Block < ' blk , ' tcx > ,
10081049 debug_loc : DebugLoc )
10091050 -> Block < ' blk , ' tcx > {
1010- let _icx = base:: push_ctxt ( "<DropValue as Cleanup>::trans" ) ;
1051+ let skip_dtor = self . skip_dtor ;
1052+ let _icx = if skip_dtor {
1053+ base:: push_ctxt ( "<DropValue as Cleanup>::trans skip_dtor=true" )
1054+ } else {
1055+ base:: push_ctxt ( "<DropValue as Cleanup>::trans skip_dtor=false" )
1056+ } ;
10111057 let bcx = if self . is_immediate {
1012- glue:: drop_ty_immediate ( bcx, self . val , self . ty , debug_loc)
1058+ glue:: drop_ty_immediate ( bcx, self . val , self . ty , debug_loc, self . skip_dtor )
10131059 } else {
1014- glue:: drop_ty ( bcx, self . val , self . ty , debug_loc)
1060+ glue:: drop_ty_core ( bcx, self . val , self . ty , debug_loc, self . skip_dtor )
10151061 } ;
1016- if self . zero {
1062+ if self . fill_on_drop {
10171063 base:: drop_done_fill_mem ( bcx, self . val , self . ty ) ;
10181064 }
10191065 bcx
@@ -1190,10 +1236,14 @@ pub trait CleanupMethods<'blk, 'tcx> {
11901236 cleanup_scope : ScopeId ,
11911237 val : ValueRef ,
11921238 ty : Ty < ' tcx > ) ;
1193- fn schedule_drop_and_zero_mem ( & self ,
1239+ fn schedule_drop_and_fill_mem ( & self ,
11941240 cleanup_scope : ScopeId ,
11951241 val : ValueRef ,
11961242 ty : Ty < ' tcx > ) ;
1243+ fn schedule_drop_enum_contents ( & self ,
1244+ cleanup_scope : ScopeId ,
1245+ val : ValueRef ,
1246+ ty : Ty < ' tcx > ) ;
11971247 fn schedule_drop_immediate ( & self ,
11981248 cleanup_scope : ScopeId ,
11991249 val : ValueRef ,
0 commit comments