@@ -138,17 +138,141 @@ pub enum Expr {
138
138
/// `val` is a pointer into memory for which a cleanup is scheduled
139
139
/// (and thus has type *T). If you move out of an Lvalue, you must
140
140
/// zero out the memory (FIXME #5016).
141
- LvalueExpr ,
141
+ LvalueExpr ( Lvalue ) ,
142
142
}
143
143
144
- #[ derive( Clone , Copy , Debug ) ]
145
- pub struct Lvalue ;
144
+ #[ derive( Copy , Clone , Debug ) ]
145
+ pub enum DropFlagInfo {
146
+ DontZeroJustUse ( ast:: NodeId ) ,
147
+ ZeroAndMaintain ( ast:: NodeId ) ,
148
+ None ,
149
+ }
150
+
151
+ impl DropFlagInfo {
152
+ pub fn must_zero ( & self ) -> bool {
153
+ match * self {
154
+ DropFlagInfo :: DontZeroJustUse ( ..) => false ,
155
+ DropFlagInfo :: ZeroAndMaintain ( ..) => true ,
156
+ DropFlagInfo :: None => true ,
157
+ }
158
+ }
159
+
160
+ pub fn hint_to_maintain ( & self ) -> Option < ast:: NodeId > {
161
+ match * self {
162
+ DropFlagInfo :: DontZeroJustUse ( id) => Some ( id) ,
163
+ DropFlagInfo :: ZeroAndMaintain ( id) => Some ( id) ,
164
+ DropFlagInfo :: None => None ,
165
+ }
166
+ }
167
+ }
168
+
169
+ // FIXME: having Lvalue be `Copy` is a bit of a footgun, since clients
170
+ // may not realize that subparts of an Lvalue can have a subset of
171
+ // drop-flags associated with them, while this as written will just
172
+ // memcpy the drop_flag_info. But, it is an easier way to get `_match`
173
+ // off the ground to just let this be `Copy` for now.
174
+ #[ derive( Copy , Clone , Debug ) ]
175
+ pub struct Lvalue {
176
+ pub source : & ' static str ,
177
+ pub drop_flag_info : DropFlagInfo
178
+ }
146
179
147
180
#[ derive( Debug ) ]
148
181
pub struct Rvalue {
149
182
pub mode : RvalueMode
150
183
}
151
184
185
+ impl Lvalue {
186
+ pub fn new ( source : & ' static str ) -> Lvalue {
187
+ Lvalue { source : source, drop_flag_info : DropFlagInfo :: None }
188
+ }
189
+
190
+ pub fn upvar < ' blk , ' tcx > ( source : & ' static str ,
191
+ bcx : Block < ' blk , ' tcx > ,
192
+ id : ast:: NodeId ) -> Lvalue {
193
+ let info = if Lvalue :: has_dropflag_hint ( bcx, id) {
194
+ DropFlagInfo :: ZeroAndMaintain ( id)
195
+ } else {
196
+ DropFlagInfo :: None
197
+ } ;
198
+ let info = if bcx. tcx ( ) . sess . nonzeroing_move_hints ( ) { info } else { DropFlagInfo :: None } ;
199
+ debug ! ( "upvar Lvalue at {}, id: {} info: {:?}" , source, id, info) ;
200
+ Lvalue { source : source, drop_flag_info : info }
201
+ }
202
+
203
+ pub fn match_input < ' blk , ' tcx > ( source : & ' static str ,
204
+ bcx : Block < ' blk , ' tcx > ,
205
+ id : ast:: NodeId ) -> Lvalue
206
+ {
207
+ let info = if Lvalue :: has_dropflag_hint ( bcx, id) {
208
+ // match_input is used to move from the input into a
209
+ // separate stack slot; it must zero (at least until we
210
+ // improve things to track drop flags for the fragmented
211
+ // parent match input expression).
212
+ DropFlagInfo :: ZeroAndMaintain ( id)
213
+ } else {
214
+ DropFlagInfo :: None
215
+ } ;
216
+ let info = if bcx. tcx ( ) . sess . nonzeroing_move_hints ( ) { info } else { DropFlagInfo :: None } ;
217
+ debug ! ( "match_input Lvalue at {}, id: {} info: {:?}" , source, id, info) ;
218
+ Lvalue { source : source, drop_flag_info : info }
219
+ }
220
+
221
+ pub fn local < ' blk , ' tcx > ( source : & ' static str ,
222
+ bcx : Block < ' blk , ' tcx > ,
223
+ id : ast:: NodeId ,
224
+ aliases_other_state : bool )
225
+ -> Lvalue
226
+ {
227
+ let info = if Lvalue :: has_dropflag_hint ( bcx, id) {
228
+ if aliases_other_state {
229
+ DropFlagInfo :: ZeroAndMaintain ( id)
230
+ } else {
231
+ DropFlagInfo :: DontZeroJustUse ( id)
232
+ }
233
+ } else {
234
+ DropFlagInfo :: None
235
+ } ;
236
+ let info = if bcx. tcx ( ) . sess . nonzeroing_move_hints ( ) { info } else { DropFlagInfo :: None } ;
237
+ debug ! ( "local Lvalue at {}, id: {} info: {:?}" , source, id, info) ;
238
+ Lvalue { source : source, drop_flag_info : info }
239
+ }
240
+
241
+ pub fn store_arg < ' blk , ' tcx > ( source : & ' static str ,
242
+ bcx : Block < ' blk , ' tcx > ,
243
+ id : ast:: NodeId ) -> Lvalue
244
+ {
245
+ let info = if Lvalue :: has_dropflag_hint ( bcx, id) {
246
+ DropFlagInfo :: ZeroAndMaintain ( id)
247
+ } else {
248
+ DropFlagInfo :: None
249
+ } ;
250
+ let info = if bcx. tcx ( ) . sess . nonzeroing_move_hints ( ) { info } else { DropFlagInfo :: None } ;
251
+ debug ! ( "store_arg Lvalue at {}, id: {} info: {:?}" , source, id, info) ;
252
+ Lvalue { source : source, drop_flag_info : info }
253
+ }
254
+
255
+ pub fn binding < ' blk , ' tcx > ( source : & ' static str ,
256
+ bcx : Block < ' blk , ' tcx > ,
257
+ id : ast:: NodeId ,
258
+ name : ast:: Name ) -> Lvalue {
259
+ let info = if Lvalue :: has_dropflag_hint ( bcx, id) {
260
+ DropFlagInfo :: DontZeroJustUse ( id)
261
+ } else {
262
+ DropFlagInfo :: None
263
+ } ;
264
+ let info = if bcx. tcx ( ) . sess . nonzeroing_move_hints ( ) { info } else { DropFlagInfo :: None } ;
265
+ debug ! ( "binding Lvalue at {}, id: {} name: {} info: {:?}" ,
266
+ source, id, name, info) ;
267
+ Lvalue { source : source, drop_flag_info : info }
268
+ }
269
+
270
+ fn has_dropflag_hint < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
271
+ id : ast:: NodeId ) -> bool {
272
+ bcx. fcx . lldropflag_hints . borrow ( ) . has_hint ( id)
273
+ }
274
+ }
275
+
152
276
impl Rvalue {
153
277
pub fn new ( m : RvalueMode ) -> Rvalue {
154
278
Rvalue { mode : m }
@@ -201,7 +325,7 @@ pub fn lvalue_scratch_datum<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
201
325
bcx. fcx . schedule_lifetime_end ( scope, scratch) ;
202
326
bcx. fcx . schedule_drop_mem ( scope, scratch, ty) ;
203
327
204
- DatumBlock :: new ( bcx, Datum :: new ( scratch, ty, Lvalue ) )
328
+ DatumBlock :: new ( bcx, Datum :: new ( scratch, ty, Lvalue :: new ( "datum::lvalue_scratch_datum" ) ) )
205
329
}
206
330
207
331
/// Allocates temporary space on the stack using alloca() and returns a by-ref Datum pointing to
@@ -308,7 +432,7 @@ impl KindOps for Lvalue {
308
432
}
309
433
310
434
fn to_expr_kind ( self ) -> Expr {
311
- LvalueExpr
435
+ LvalueExpr ( self )
312
436
}
313
437
}
314
438
@@ -319,14 +443,14 @@ impl KindOps for Expr {
319
443
ty : Ty < ' tcx > )
320
444
-> Block < ' blk , ' tcx > {
321
445
match * self {
322
- LvalueExpr => Lvalue . post_store ( bcx, val, ty) ,
446
+ LvalueExpr ( ref l ) => l . post_store ( bcx, val, ty) ,
323
447
RvalueExpr ( ref r) => r. post_store ( bcx, val, ty) ,
324
448
}
325
449
}
326
450
327
451
fn is_by_ref ( & self ) -> bool {
328
452
match * self {
329
- LvalueExpr => Lvalue . is_by_ref ( ) ,
453
+ LvalueExpr ( ref l ) => l . is_by_ref ( ) ,
330
454
RvalueExpr ( ref r) => r. is_by_ref ( )
331
455
}
332
456
}
@@ -360,7 +484,10 @@ impl<'tcx> Datum<'tcx, Rvalue> {
360
484
match self . kind . mode {
361
485
ByRef => {
362
486
add_rvalue_clean ( ByRef , fcx, scope, self . val , self . ty ) ;
363
- DatumBlock :: new ( bcx, Datum :: new ( self . val , self . ty , Lvalue ) )
487
+ DatumBlock :: new ( bcx, Datum :: new (
488
+ self . val ,
489
+ self . ty ,
490
+ Lvalue :: new ( "datum::to_lvalue_datum_in_scope" ) ) )
364
491
}
365
492
366
493
ByValue => {
@@ -417,7 +544,7 @@ impl<'tcx> Datum<'tcx, Expr> {
417
544
{
418
545
let Datum { val, ty, kind } = self ;
419
546
match kind {
420
- LvalueExpr => if_lvalue ( Datum :: new ( val, ty, Lvalue ) ) ,
547
+ LvalueExpr ( l ) => if_lvalue ( Datum :: new ( val, ty, l ) ) ,
421
548
RvalueExpr ( r) => if_rvalue ( Datum :: new ( val, ty, r) ) ,
422
549
}
423
550
}
@@ -528,7 +655,7 @@ impl<'tcx> Datum<'tcx, Lvalue> {
528
655
} ;
529
656
Datum {
530
657
val : val,
531
- kind : Lvalue ,
658
+ kind : Lvalue :: new ( "Datum::get_element" ) ,
532
659
ty : ty,
533
660
}
534
661
}
0 commit comments