11//! This pass transforms derefs of Box into a deref of the pointer inside Box. 
22//! 
33//! Box is not actually a pointer so it is incorrect to dereference it directly. 
4+ //! 
5+ //! `ShallowInitBox` being a device for drop elaboration to understand deferred assignment to box 
6+ //! contents, we do not need this any more on runtime MIR. 
47
5- use  rustc_abi:: FieldIdx ; 
6- use  rustc_hir :: def_id :: DefId ; 
8+ use  rustc_abi:: { FieldIdx ,   VariantIdx } ; 
9+ use  rustc_index :: { IndexVec ,  indexvec } ; 
710use  rustc_middle:: mir:: visit:: MutVisitor ; 
811use  rustc_middle:: mir:: * ; 
912use  rustc_middle:: span_bug; 
10- use  rustc_middle:: ty:: { Ty ,  TyCtxt } ; 
13+ use  rustc_middle:: ty:: { self ,   Ty ,  TyCtxt } ; 
1114
1215use  crate :: patch:: MirPatch ; 
1316
1417/// Constructs the types used when accessing a Box's pointer 
1518fn  build_ptr_tys < ' tcx > ( 
1619    tcx :  TyCtxt < ' tcx > , 
1720    pointee :  Ty < ' tcx > , 
18-     unique_did :   DefId , 
19-     nonnull_did :   DefId , 
21+     unique_def :  ty :: AdtDef < ' tcx > , 
22+     nonnull_def :  ty :: AdtDef < ' tcx > , 
2023)  -> ( Ty < ' tcx > ,  Ty < ' tcx > ,  Ty < ' tcx > )  { 
2124    let  args = tcx. mk_args ( & [ pointee. into ( ) ] ) ; 
22-     let  unique_ty = tcx . type_of ( unique_did ) . instantiate ( tcx,  args) ; 
23-     let  nonnull_ty = tcx . type_of ( nonnull_did ) . instantiate ( tcx,  args) ; 
25+     let  unique_ty = Ty :: new_adt ( tcx,  unique_def ,  args) ; 
26+     let  nonnull_ty = Ty :: new_adt ( tcx,  nonnull_def ,  args) ; 
2427    let  ptr_ty = Ty :: new_imm_ptr ( tcx,  pointee) ; 
2528
2629    ( unique_ty,  nonnull_ty,  ptr_ty) 
@@ -36,8 +39,8 @@ pub(super) fn build_projection<'tcx>(
3639
3740struct  ElaborateBoxDerefVisitor < ' a ,  ' tcx >  { 
3841    tcx :  TyCtxt < ' tcx > , 
39-     unique_did :   DefId , 
40-     nonnull_did :   DefId , 
42+     unique_def :  ty :: AdtDef < ' tcx > , 
43+     nonnull_def :  ty :: AdtDef < ' tcx > , 
4144    local_decls :  & ' a  mut  LocalDecls < ' tcx > , 
4245    patch :  MirPatch < ' tcx > , 
4346} 
@@ -64,7 +67,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
6467            let  source_info = self . local_decls [ place. local ] . source_info ; 
6568
6669            let  ( unique_ty,  nonnull_ty,  ptr_ty)  =
67-                 build_ptr_tys ( tcx,  boxed_ty,  self . unique_did ,  self . nonnull_did ) ; 
70+                 build_ptr_tys ( tcx,  boxed_ty,  self . unique_def ,  self . nonnull_def ) ; 
6871
6972            let  ptr_local = self . patch . new_temp ( ptr_ty,  source_info. span ) ; 
7073
@@ -86,6 +89,68 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
8689
8790        self . super_place ( place,  context,  location) ; 
8891    } 
92+ 
93+     fn  visit_statement ( & mut  self ,  stmt :  & mut  Statement < ' tcx > ,  location :  Location )  { 
94+         self . super_statement ( stmt,  location) ; 
95+ 
96+         let  tcx = self . tcx ; 
97+         let  source_info = stmt. source_info ; 
98+ 
99+         if  let  StatementKind :: Assign ( box ( _,  ref  mut  rvalue) )  = stmt. kind 
100+             && let  Rvalue :: ShallowInitBox ( ref  mut  mutptr_to_u8,  pointee)  = * rvalue
101+             && let  ty:: Adt ( box_adt,  box_args)  = Ty :: new_box ( tcx,  pointee) . kind ( ) 
102+         { 
103+             let  args = tcx. mk_args ( & [ pointee. into ( ) ] ) ; 
104+             let  ( unique_ty,  nonnull_ty,  ptr_ty)  =
105+                 build_ptr_tys ( tcx,  pointee,  self . unique_def ,  self . nonnull_def ) ; 
106+             let  adt_kind = |def :  ty:: AdtDef < ' tcx > ,  args| { 
107+                 Box :: new ( AggregateKind :: Adt ( def. did ( ) ,  VariantIdx :: ZERO ,  args,  None ,  None ) ) 
108+             } ; 
109+             let  zst = |ty| { 
110+                 Operand :: Constant ( Box :: new ( ConstOperand  { 
111+                     span :  source_info. span , 
112+                     user_ty :  None , 
113+                     const_ :  Const :: zero_sized ( ty) , 
114+                 } ) ) 
115+             } ; 
116+ 
117+             let  constptr = self . patch . new_temp ( ptr_ty,  source_info. span ) ; 
118+             self . patch . add_assign ( 
119+                 location, 
120+                 constptr. into ( ) , 
121+                 Rvalue :: Cast ( CastKind :: Transmute ,  mutptr_to_u8. clone ( ) ,  ptr_ty) , 
122+             ) ; 
123+ 
124+             let  nonnull = self . patch . new_temp ( nonnull_ty,  source_info. span ) ; 
125+             self . patch . add_assign ( 
126+                 location, 
127+                 nonnull. into ( ) , 
128+                 Rvalue :: Aggregate ( 
129+                     adt_kind ( self . nonnull_def ,  args) , 
130+                     indexvec ! [ Operand :: Move ( constptr. into( ) ) ] , 
131+                 ) , 
132+             ) ; 
133+ 
134+             let  unique = self . patch . new_temp ( unique_ty,  source_info. span ) ; 
135+             let  phantomdata_ty =
136+                 self . unique_def . non_enum_variant ( ) . fields [ FieldIdx :: ONE ] . ty ( tcx,  args) ; 
137+             self . patch . add_assign ( 
138+                 location, 
139+                 unique. into ( ) , 
140+                 Rvalue :: Aggregate ( 
141+                     adt_kind ( self . unique_def ,  args) , 
142+                     indexvec ! [ Operand :: Move ( nonnull. into( ) ) ,  zst( phantomdata_ty) ] , 
143+                 ) , 
144+             ) ; 
145+ 
146+             let  global_alloc_ty =
147+                 box_adt. non_enum_variant ( ) . fields [ FieldIdx :: ONE ] . ty ( tcx,  box_args) ; 
148+             * rvalue = Rvalue :: Aggregate ( 
149+                 adt_kind ( * box_adt,  box_args) , 
150+                 indexvec ! [ Operand :: Move ( unique. into( ) ) ,  zst( global_alloc_ty) ] , 
151+             ) ; 
152+         } 
153+     } 
89154} 
90155
91156pub ( super )  struct  ElaborateBoxDerefs ; 
@@ -97,18 +162,22 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
97162
98163        let  unique_did = tcx. adt_def ( def_id) . non_enum_variant ( ) . fields [ FieldIdx :: ZERO ] . did ; 
99164
100-         let  Some ( nonnull_def )  = tcx. type_of ( unique_did) . instantiate_identity ( ) . ty_adt_def ( )  else  { 
165+         let  Some ( unique_def )  = tcx. type_of ( unique_did) . instantiate_identity ( ) . ty_adt_def ( )  else  { 
101166            span_bug ! ( tcx. def_span( unique_did) ,  "expected Box to contain Unique" ) 
102167        } ; 
103168
104-         let  nonnull_did = nonnull_def. non_enum_variant ( ) . fields [ FieldIdx :: ZERO ] . did ; 
169+         let  nonnull_did = unique_def. non_enum_variant ( ) . fields [ FieldIdx :: ZERO ] . did ; 
170+ 
171+         let  Some ( nonnull_def)  = tcx. type_of ( nonnull_did) . instantiate_identity ( ) . ty_adt_def ( )  else  { 
172+             span_bug ! ( tcx. def_span( nonnull_did) ,  "expected Unique to contain Nonnull" ) 
173+         } ; 
105174
106175        let  patch = MirPatch :: new ( body) ; 
107176
108177        let  local_decls = & mut  body. local_decls ; 
109178
110179        let  mut  visitor =
111-             ElaborateBoxDerefVisitor  {  tcx,  unique_did ,  nonnull_did ,  local_decls,  patch } ; 
180+             ElaborateBoxDerefVisitor  {  tcx,  unique_def ,  nonnull_def ,  local_decls,  patch } ; 
112181
113182        for  ( block,  data)  in  body. basic_blocks . as_mut_preserves_cfg ( ) . iter_enumerated_mut ( )  { 
114183            visitor. visit_basic_block_data ( block,  data) ; 
@@ -131,7 +200,7 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
131200                            new_projections. get_or_insert_with ( || base. projection . to_vec ( ) ) ; 
132201
133202                        let  ( unique_ty,  nonnull_ty,  ptr_ty)  =
134-                             build_ptr_tys ( tcx,  boxed_ty,  unique_did ,  nonnull_did ) ; 
203+                             build_ptr_tys ( tcx,  boxed_ty,  unique_def ,  nonnull_def ) ; 
135204
136205                        new_projections. extend_from_slice ( & build_projection ( unique_ty,  nonnull_ty) ) ; 
137206                        // While we can't project into `NonNull<_>` in a basic block 
0 commit comments