@@ -25,12 +25,13 @@ use syntax::ast::LitKind;
2525use syntax:: symbol:: sym;
2626use syntax_pos:: { Span , DUMMY_SP } ;
2727
28- use rustc_index:: bit_set:: BitSet ;
2928use rustc_index:: vec:: { IndexVec , Idx } ;
3029use rustc_target:: spec:: abi:: Abi ;
3130
3231use std:: { iter, mem, usize} ;
3332
33+ use crate :: transform:: check_consts:: { qualifs, Item as ConstCx } ;
34+
3435/// State of a temporary during collection and promotion.
3536#[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
3637pub enum TempState {
@@ -231,9 +232,9 @@ struct Validator<'a, 'tcx> {
231232 is_static_mut : bool ,
232233 is_non_const_fn : bool ,
233234 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 > ,
237238
238239 /// Explicit promotion happens e.g. for constant arguments declared via
239240 /// `rustc_args_required_const`.
@@ -276,15 +277,17 @@ impl<'tcx> Validator<'_, 'tcx> {
276277 PlaceBase :: Local ( local) => local,
277278 _ => return Err ( Unpromotable ) ,
278279 } ;
280+ self . validate_local ( base) ?;
281+
279282 if place. projection . contains ( & ProjectionElem :: Deref ) {
280283 return Err ( Unpromotable ) ;
281284 }
282285
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) ;
285288 // HACK(eddyb) this should compute the same thing as
286289 // `<HasMutInterior as Qualif>::in_projection` from
287- // `qualify_consts ` but without recursion.
290+ // `check_consts::qualifs ` but without recursion.
288291 if has_mut_interior {
289292 // This allows borrowing fields which don't have
290293 // `HasMutInterior`, from a type that does, e.g.:
@@ -311,8 +314,7 @@ impl<'tcx> Validator<'_, 'tcx> {
311314 if has_mut_interior {
312315 return Err ( Unpromotable ) ;
313316 }
314- // FIXME(eddyb) compute this on the fly.
315- if self . needs_drop . contains ( base) {
317+ if self . qualif_local :: < qualifs:: NeedsDrop > ( base) {
316318 return Err ( Unpromotable ) ;
317319 }
318320 if let BorrowKind :: Mut { .. } = kind {
@@ -339,7 +341,7 @@ impl<'tcx> Validator<'_, 'tcx> {
339341 }
340342 }
341343
342- self . validate_local ( base )
344+ Ok ( ( ) )
343345 }
344346 _ => bug ! ( )
345347 }
@@ -373,6 +375,42 @@ impl<'tcx> Validator<'_, 'tcx> {
373375 }
374376 }
375377
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+
376414 // FIXME(eddyb) maybe cache this?
377415 fn validate_local ( & self , local : Local ) -> Result < ( ) , Unpromotable > {
378416 if let TempState :: Defined { location : loc, .. } = self . temps [ local] {
@@ -593,13 +631,14 @@ impl<'tcx> Validator<'_, 'tcx> {
593631 }
594632 }
595633
634+ self . validate_place ( place) ?;
635+
596636 // HACK(eddyb) this should compute the same thing as
597637 // `<HasMutInterior as Qualif>::in_projection` from
598- // `qualify_consts ` but without recursion.
638+ // `check_consts::qualifs ` but without recursion.
599639 let mut has_mut_interior = match place. base {
600640 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)
603642 }
604643 PlaceBase :: Static ( _) => false ,
605644 } ;
@@ -624,7 +663,7 @@ impl<'tcx> Validator<'_, 'tcx> {
624663 return Err ( Unpromotable ) ;
625664 }
626665
627- self . validate_place ( place )
666+ Ok ( ( ) )
628667 }
629668
630669 Rvalue :: Aggregate ( _, ref operands) => {
@@ -680,9 +719,6 @@ pub fn validate_candidates(
680719 body : & Body < ' tcx > ,
681720 def_id : DefId ,
682721 temps : & IndexVec < Local , TempState > ,
683- // FIXME(eddyb) compute these 2 on the fly.
684- has_mut_interior : & BitSet < Local > ,
685- needs_drop : & BitSet < Local > ,
686722 candidates : & [ Candidate ] ,
687723) -> Vec < Candidate > {
688724 let mut validator = Validator {
@@ -693,9 +729,8 @@ pub fn validate_candidates(
693729 is_static_mut : false ,
694730 is_non_const_fn : false ,
695731 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) ,
699734
700735 explicit : false ,
701736 } ;
0 commit comments