@@ -5,6 +5,7 @@ use rustc_index::vec::Idx;
5
5
use crate :: build:: expr:: as_place:: PlaceBase ;
6
6
use crate :: build:: expr:: category:: { Category , RvalueFunc } ;
7
7
use crate :: build:: { BlockAnd , BlockAndExtension , Builder } ;
8
+ use rustc_hir:: lang_items:: LangItem ;
8
9
use rustc_middle:: middle:: region;
9
10
use rustc_middle:: mir:: AssertKind ;
10
11
use rustc_middle:: mir:: Place ;
@@ -88,6 +89,56 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
88
89
}
89
90
ExprKind :: Box { value } => {
90
91
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
+
91
142
// The `Box<T>` temporary created here is not a part of the HIR,
92
143
// and therefore is not considered during generator auto-trait
93
144
// determination. See the comment about `box` at `yield_in_scope`.
@@ -101,8 +152,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
101
152
this. schedule_drop_storage_and_value ( expr_span, scope, result) ;
102
153
}
103
154
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 ) ;
106
157
this. cfg . push_assign ( block, source_info, Place :: from ( result) , box_) ;
107
158
108
159
// initialize the box contents:
0 commit comments