@@ -25,12 +25,13 @@ use syntax::ast::LitKind;
25
25
use syntax:: symbol:: sym;
26
26
use syntax_pos:: { Span , DUMMY_SP } ;
27
27
28
- use rustc_index:: bit_set:: BitSet ;
29
28
use rustc_index:: vec:: { IndexVec , Idx } ;
30
29
use rustc_target:: spec:: abi:: Abi ;
31
30
32
31
use std:: { iter, mem, usize} ;
33
32
33
+ use crate :: transform:: check_consts:: { qualifs, Item as ConstCx } ;
34
+
34
35
/// State of a temporary during collection and promotion.
35
36
#[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
36
37
pub enum TempState {
@@ -231,9 +232,9 @@ struct Validator<'a, 'tcx> {
231
232
is_static_mut : bool ,
232
233
is_non_const_fn : bool ,
233
234
temps : & ' a IndexVec < Local , TempState > ,
234
- // FIXME(eddyb) compute these 2 on the fly.
235
- has_mut_interior : & ' a BitSet < Local > ,
236
- needs_drop : & ' a BitSet < Local > ,
235
+
236
+ // FIXME(eddyb) deduplicate the data in this vs other fields.
237
+ const_cx : ConstCx < ' a , ' tcx > ,
237
238
238
239
/// Explicit promotion happens e.g. for constant arguments declared via
239
240
/// `rustc_args_required_const`.
@@ -276,15 +277,17 @@ impl<'tcx> Validator<'_, 'tcx> {
276
277
PlaceBase :: Local ( local) => local,
277
278
_ => return Err ( Unpromotable ) ,
278
279
} ;
280
+ self . validate_local ( base) ?;
281
+
279
282
if place. projection . contains ( & ProjectionElem :: Deref ) {
280
283
return Err ( Unpromotable ) ;
281
284
}
282
285
283
- // FIXME(eddyb) compute this on the fly.
284
- let mut has_mut_interior = self . has_mut_interior . contains ( base) ;
286
+ let mut has_mut_interior =
287
+ self . qualif_local :: < qualifs :: HasMutInterior > ( base) ;
285
288
// HACK(eddyb) this should compute the same thing as
286
289
// `<HasMutInterior as Qualif>::in_projection` from
287
- // `qualify_consts ` but without recursion.
290
+ // `check_consts::qualifs ` but without recursion.
288
291
if has_mut_interior {
289
292
// This allows borrowing fields which don't have
290
293
// `HasMutInterior`, from a type that does, e.g.:
@@ -311,8 +314,7 @@ impl<'tcx> Validator<'_, 'tcx> {
311
314
if has_mut_interior {
312
315
return Err ( Unpromotable ) ;
313
316
}
314
- // FIXME(eddyb) compute this on the fly.
315
- if self . needs_drop . contains ( base) {
317
+ if self . qualif_local :: < qualifs:: NeedsDrop > ( base) {
316
318
return Err ( Unpromotable ) ;
317
319
}
318
320
if let BorrowKind :: Mut { .. } = kind {
@@ -339,7 +341,7 @@ impl<'tcx> Validator<'_, 'tcx> {
339
341
}
340
342
}
341
343
342
- self . validate_local ( base )
344
+ Ok ( ( ) )
343
345
}
344
346
_ => bug ! ( )
345
347
}
@@ -373,6 +375,42 @@ impl<'tcx> Validator<'_, 'tcx> {
373
375
}
374
376
}
375
377
378
+ // FIXME(eddyb) maybe cache this?
379
+ fn qualif_local < Q : qualifs:: Qualif > ( & self , local : Local ) -> bool {
380
+ let per_local = & |l| self . qualif_local :: < Q > ( l) ;
381
+
382
+ if let TempState :: Defined { location : loc, .. } = self . temps [ local] {
383
+ let num_stmts = self . body [ loc. block ] . statements . len ( ) ;
384
+
385
+ if loc. statement_index < num_stmts {
386
+ let statement = & self . body [ loc. block ] . statements [ loc. statement_index ] ;
387
+ match & statement. kind {
388
+ StatementKind :: Assign ( box( _, rhs) ) => {
389
+ Q :: in_rvalue ( & self . const_cx , per_local, rhs)
390
+ }
391
+ _ => {
392
+ span_bug ! ( statement. source_info. span, "{:?} is not an assignment" ,
393
+ statement) ;
394
+ }
395
+ }
396
+ } else {
397
+ let terminator = self . body [ loc. block ] . terminator ( ) ;
398
+ match & terminator. kind {
399
+ TerminatorKind :: Call { func, args, .. } => {
400
+ let return_ty = self . body . local_decls [ local] . ty ;
401
+ Q :: in_call ( & self . const_cx , per_local, func, args, return_ty)
402
+ }
403
+ kind => {
404
+ span_bug ! ( terminator. source_info. span, "{:?} not promotable" , kind) ;
405
+ }
406
+ }
407
+ }
408
+ } else {
409
+ let span = self . body . local_decls [ local] . source_info . span ;
410
+ span_bug ! ( span, "{:?} not promotable, qualif_local shouldn't have been called" , local) ;
411
+ }
412
+ }
413
+
376
414
// FIXME(eddyb) maybe cache this?
377
415
fn validate_local ( & self , local : Local ) -> Result < ( ) , Unpromotable > {
378
416
if let TempState :: Defined { location : loc, .. } = self . temps [ local] {
@@ -593,13 +631,14 @@ impl<'tcx> Validator<'_, 'tcx> {
593
631
}
594
632
}
595
633
634
+ self . validate_place ( place) ?;
635
+
596
636
// HACK(eddyb) this should compute the same thing as
597
637
// `<HasMutInterior as Qualif>::in_projection` from
598
- // `qualify_consts ` but without recursion.
638
+ // `check_consts::qualifs ` but without recursion.
599
639
let mut has_mut_interior = match place. base {
600
640
PlaceBase :: Local ( local) => {
601
- // FIXME(eddyb) compute this on the fly.
602
- self . has_mut_interior . contains ( * local)
641
+ self . qualif_local :: < qualifs:: HasMutInterior > ( * local)
603
642
}
604
643
PlaceBase :: Static ( _) => false ,
605
644
} ;
@@ -624,7 +663,7 @@ impl<'tcx> Validator<'_, 'tcx> {
624
663
return Err ( Unpromotable ) ;
625
664
}
626
665
627
- self . validate_place ( place )
666
+ Ok ( ( ) )
628
667
}
629
668
630
669
Rvalue :: Aggregate ( _, ref operands) => {
@@ -680,9 +719,6 @@ pub fn validate_candidates(
680
719
body : & Body < ' tcx > ,
681
720
def_id : DefId ,
682
721
temps : & IndexVec < Local , TempState > ,
683
- // FIXME(eddyb) compute these 2 on the fly.
684
- has_mut_interior : & BitSet < Local > ,
685
- needs_drop : & BitSet < Local > ,
686
722
candidates : & [ Candidate ] ,
687
723
) -> Vec < Candidate > {
688
724
let mut validator = Validator {
@@ -693,9 +729,8 @@ pub fn validate_candidates(
693
729
is_static_mut : false ,
694
730
is_non_const_fn : false ,
695
731
temps,
696
- // FIXME(eddyb) compute these 2 on the fly.
697
- has_mut_interior,
698
- needs_drop,
732
+
733
+ const_cx : ConstCx :: for_promotion ( tcx, def_id, body) ,
699
734
700
735
explicit : false ,
701
736
} ;
0 commit comments