@@ -1023,6 +1023,25 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
1023
1023
bcx
1024
1024
}
1025
1025
1026
+ // Sets each dropflag hint (if any) for bindings to `dropflag_hint_val`.
1027
+ fn set_lllocals_hints < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
1028
+ bindings_map : & BindingsMap < ' tcx > ,
1029
+ drop_flag_hint_value : u8 )
1030
+ -> Block < ' blk , ' tcx > {
1031
+ let lllocals = bcx. fcx . lllocals . borrow ( ) ;
1032
+ for ( & ident, & binding_info) in bindings_map {
1033
+ let datum = lllocals. get ( & binding_info. id ) . unwrap ( ) ;
1034
+ if let Some ( hint) = datum. kind . dropflag_hint ( bcx) {
1035
+ let hint_value = drop_flag_hint_value as usize ;
1036
+ debug ! ( "set_lllocals_hints store hint_value={} for hint={:?} ident={}" ,
1037
+ hint_value, hint, ident) ;
1038
+ Store ( bcx, C_u8 ( bcx. fcx . ccx , hint_value) , hint. to_value ( ) . value ( ) ) ;
1039
+ }
1040
+ }
1041
+
1042
+ bcx
1043
+ }
1044
+
1026
1045
fn compile_guard < ' a , ' p , ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
1027
1046
guard_expr : & ast:: Expr ,
1028
1047
data : & ArmData < ' p , ' blk , ' tcx > ,
@@ -1635,6 +1654,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
1635
1654
// insert bindings into the lllocals map and add cleanups
1636
1655
let cs = fcx. push_custom_cleanup_scope ( ) ;
1637
1656
bcx = insert_lllocals ( bcx, & arm_data. bindings_map , Some ( cleanup:: CustomScope ( cs) ) ) ;
1657
+ bcx = set_lllocals_hints ( bcx, & arm_data. bindings_map , adt:: DTOR_NEEDED_HINT ) ;
1638
1658
bcx = expr:: trans_into ( bcx, & * arm_data. arm . body , dest) ;
1639
1659
bcx = fcx. pop_and_trans_custom_cleanup_scope ( bcx, cs) ;
1640
1660
arm_cxs. push ( bcx) ;
@@ -1666,16 +1686,10 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1666
1686
bcx = mk_binding_alloca (
1667
1687
bcx, p_id, path1. node . name , scope, ( ) ,
1668
1688
"_match::store_local::create_dummy_locals" ,
1689
+ // Dummy-locals start out uninitialized, so set their
1690
+ // drop-flag hints (if any) to "moved."
1691
+ adt:: DTOR_MOVED_HINT ,
1669
1692
|( ) , bcx, Datum { val : llval, ty, kind } | {
1670
- // Dummy-locals start out uninitialized, so set their
1671
- // drop-flag hints (if any) to "moved."
1672
- if let Some ( hint) = kind. dropflag_hint ( bcx) {
1673
- let moved_hint = adt:: DTOR_MOVED_HINT as usize ;
1674
- debug ! ( "store moved_hint={} for hint={:?}, uninitialized dummy" ,
1675
- moved_hint, hint) ;
1676
- Store ( bcx, C_u8 ( bcx. fcx . ccx , moved_hint) , hint. to_value ( ) . value ( ) ) ;
1677
- }
1678
-
1679
1693
if kind. drop_flag_info . must_zero ( ) {
1680
1694
// if no drop-flag hint, or the hint requires
1681
1695
// we maintain the embedded drop-flag, then
@@ -1707,6 +1721,9 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1707
1721
return mk_binding_alloca (
1708
1722
bcx, pat. id , ident. name , var_scope, ( ) ,
1709
1723
"_match::store_local" ,
1724
+ // Issue #27401: `let x = expr;` means drop
1725
+ // flag hint needs to be (re-)initialized.
1726
+ adt:: DTOR_NEEDED_HINT ,
1710
1727
|( ) , bcx, Datum { val : v, .. } | expr:: trans_into ( bcx, & * * init_expr,
1711
1728
expr:: SaveIn ( v) ) ) ;
1712
1729
}
@@ -1735,6 +1752,7 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
1735
1752
cleanup_scope : cleanup:: ScopeId ,
1736
1753
arg : A ,
1737
1754
caller_name : & ' static str ,
1755
+ drop_flag_hint_value : u8 ,
1738
1756
populate : F )
1739
1757
-> Block < ' blk , ' tcx > where
1740
1758
F : FnOnce ( A , Block < ' blk , ' tcx > , Datum < ' tcx , Lvalue > ) -> Block < ' blk , ' tcx > ,
@@ -1749,6 +1767,15 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
1749
1767
// Subtle: be sure that we *populate* the memory *before*
1750
1768
// we schedule the cleanup.
1751
1769
let bcx = populate ( arg, bcx, datum) ;
1770
+
1771
+ // Set the drop-flag hint, if any, to the value provided by context
1772
+ if let Some ( hint) = datum. kind . dropflag_hint ( bcx) {
1773
+ let hint_value = drop_flag_hint_value as usize ;
1774
+ debug ! ( "mk_binding_alloca store hint_value={} for hint={:?}, name={}" ,
1775
+ hint_value, hint, name) ;
1776
+ Store ( bcx, C_u8 ( bcx. fcx . ccx , hint_value) , hint. to_value ( ) . value ( ) ) ;
1777
+ }
1778
+
1752
1779
bcx. fcx . schedule_lifetime_end ( cleanup_scope, llval) ;
1753
1780
bcx. fcx . schedule_drop_mem ( cleanup_scope, llval, var_ty, lvalue. dropflag_hint ( bcx) ) ;
1754
1781
@@ -1799,6 +1826,10 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1799
1826
bcx = mk_binding_alloca (
1800
1827
bcx, pat. id , path1. node . name , cleanup_scope, ( ) ,
1801
1828
"_match::bind_irrefutable_pat" ,
1829
+ // Issue #27401: `match ... { PAT[x] => ... }`
1830
+ // means drop flag hint for `x` needs to be
1831
+ // (re-)initialized.
1832
+ adt:: DTOR_NEEDED_HINT ,
1802
1833
|( ) , bcx, Datum { val : llval, ty, kind : _ } | {
1803
1834
match pat_binding_mode {
1804
1835
ast:: BindByValue ( _) => {
0 commit comments