@@ -5,6 +5,7 @@ use rustc_index::vec::Idx;
55use crate :: build:: expr:: as_place:: PlaceBase ;
66use crate :: build:: expr:: category:: { Category , RvalueFunc } ;
77use crate :: build:: { BlockAnd , BlockAndExtension , Builder } ;
8+ use rustc_hir:: lang_items:: LangItem ;
89use rustc_middle:: middle:: region;
910use rustc_middle:: mir:: AssertKind ;
1011use rustc_middle:: mir:: Place ;
@@ -88,6 +89,56 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8889 }
8990 ExprKind :: Box { value } => {
9091 let value = & this. thir [ value] ;
92+ let tcx = this. tcx ;
93+
94+ // `exchange_malloc` is unsafe but box is safe, so need a new scope.
95+ let synth_scope = this. new_source_scope (
96+ expr_span,
97+ LintLevel :: Inherited ,
98+ Some ( Safety :: BuiltinUnsafe ) ,
99+ ) ;
100+ let synth_info = SourceInfo { span : expr_span, scope : synth_scope } ;
101+
102+ let size = this. temp ( tcx. types . usize , expr_span) ;
103+ this. cfg . push_assign (
104+ block,
105+ synth_info,
106+ size,
107+ Rvalue :: NullaryOp ( NullOp :: SizeOf , value. ty ) ,
108+ ) ;
109+
110+ let align = this. temp ( tcx. types . usize , expr_span) ;
111+ this. cfg . push_assign (
112+ block,
113+ synth_info,
114+ align,
115+ Rvalue :: NullaryOp ( NullOp :: AlignOf , value. ty ) ,
116+ ) ;
117+
118+ // malloc some memory of suitable size and align:
119+ let exchange_malloc = Operand :: function_handle (
120+ tcx,
121+ tcx. require_lang_item ( LangItem :: ExchangeMalloc , Some ( expr_span) ) ,
122+ ty:: List :: empty ( ) ,
123+ expr_span,
124+ ) ;
125+ let storage = this. temp ( tcx. mk_mut_ptr ( tcx. types . u8 ) , expr_span) ;
126+ let success = this. cfg . start_new_block ( ) ;
127+ this. cfg . terminate (
128+ block,
129+ synth_info,
130+ TerminatorKind :: Call {
131+ func : exchange_malloc,
132+ args : vec ! [ Operand :: Move ( size) , Operand :: Move ( align) ] ,
133+ destination : Some ( ( Place :: from ( storage) , success) ) ,
134+ cleanup : None ,
135+ from_hir_call : false ,
136+ fn_span : expr_span,
137+ } ,
138+ ) ;
139+ this. diverge_from ( block) ;
140+ block = success;
141+
91142 // The `Box<T>` temporary created here is not a part of the HIR,
92143 // and therefore is not considered during generator auto-trait
93144 // determination. See the comment about `box` at `yield_in_scope`.
@@ -101,8 +152,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
101152 this. schedule_drop_storage_and_value ( expr_span, scope, result) ;
102153 }
103154
104- // malloc some memory of suitable type (thus far, uninitialized):
105- let box_ = Rvalue :: NullaryOp ( NullOp :: Box , value. ty ) ;
155+ // Transmute `*mut u8` to the box (thus far, uninitialized):
156+ let box_ = Rvalue :: ShallowInitBox ( Operand :: Move ( Place :: from ( storage ) ) , value. ty ) ;
106157 this. cfg . push_assign ( block, source_info, Place :: from ( result) , box_) ;
107158
108159 // initialize the box contents:
0 commit comments