11//! Propagates constants for early reporting of statically known
22//! assertion failures
33
4+ use crate :: const_prop:: CanConstProp ;
45use crate :: const_prop:: ConstPropMachine ;
56use crate :: const_prop:: ConstPropMode ;
67use crate :: MirLint ;
@@ -13,11 +14,11 @@ use rustc_hir::def::DefKind;
1314use rustc_hir:: HirId ;
1415use rustc_index:: bit_set:: BitSet ;
1516use rustc_index:: vec:: IndexVec ;
16- use rustc_middle:: mir:: visit:: { MutatingUseContext , NonMutatingUseContext , PlaceContext , Visitor } ;
17+ use rustc_middle:: mir:: visit:: Visitor ;
1718use rustc_middle:: mir:: {
18- AssertKind , BinOp , Body , Constant , ConstantKind , Local , LocalDecl , LocalKind , Location ,
19- Operand , Place , Rvalue , SourceInfo , SourceScope , SourceScopeData , Statement , StatementKind ,
20- Terminator , TerminatorKind , UnOp , RETURN_PLACE ,
19+ AssertKind , BinOp , Body , Constant , ConstantKind , Local , LocalDecl , Location , Operand , Place ,
20+ Rvalue , SourceInfo , SourceScope , SourceScopeData , Statement , StatementKind , Terminator ,
21+ TerminatorKind , UnOp , RETURN_PLACE ,
2122} ;
2223use rustc_middle:: ty:: layout:: { LayoutError , LayoutOf , LayoutOfHelpers , TyAndLayout } ;
2324use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
@@ -522,125 +523,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
522523 }
523524}
524525
525- struct CanConstProp {
526- can_const_prop : IndexVec < Local , ConstPropMode > ,
527- // False at the beginning. Once set, no more assignments are allowed to that local.
528- found_assignment : BitSet < Local > ,
529- // Cache of locals' information
530- local_kinds : IndexVec < Local , LocalKind > ,
531- }
532-
533- impl CanConstProp {
534- /// Returns true if `local` can be propagated
535- fn check < ' tcx > (
536- tcx : TyCtxt < ' tcx > ,
537- param_env : ParamEnv < ' tcx > ,
538- body : & Body < ' tcx > ,
539- ) -> IndexVec < Local , ConstPropMode > {
540- let mut cpv = CanConstProp {
541- can_const_prop : IndexVec :: from_elem ( ConstPropMode :: FullConstProp , & body. local_decls ) ,
542- found_assignment : BitSet :: new_empty ( body. local_decls . len ( ) ) ,
543- local_kinds : IndexVec :: from_fn_n (
544- |local| body. local_kind ( local) ,
545- body. local_decls . len ( ) ,
546- ) ,
547- } ;
548- for ( local, val) in cpv. can_const_prop . iter_enumerated_mut ( ) {
549- let ty = body. local_decls [ local] . ty ;
550- match tcx. layout_of ( param_env. and ( ty) ) {
551- Ok ( layout) if layout. size < Size :: from_bytes ( MAX_ALLOC_LIMIT ) => { }
552- // Either the layout fails to compute, then we can't use this local anyway
553- // or the local is too large, then we don't want to.
554- _ => {
555- * val = ConstPropMode :: NoPropagation ;
556- continue ;
557- }
558- }
559- // Cannot use args at all
560- // Cannot use locals because if x < y { y - x } else { x - y } would
561- // lint for x != y
562- // FIXME(oli-obk): lint variables until they are used in a condition
563- // FIXME(oli-obk): lint if return value is constant
564- if cpv. local_kinds [ local] == LocalKind :: Arg {
565- * val = ConstPropMode :: OnlyPropagateInto ;
566- trace ! (
567- "local {:?} can't be const propagated because it's a function argument" ,
568- local
569- ) ;
570- } else if cpv. local_kinds [ local] == LocalKind :: Var {
571- * val = ConstPropMode :: OnlyInsideOwnBlock ;
572- trace ! (
573- "local {:?} will only be propagated inside its block, because it's a user variable" ,
574- local
575- ) ;
576- }
577- }
578- cpv. visit_body ( & body) ;
579- cpv. can_const_prop
580- }
581- }
582-
583- impl Visitor < ' _ > for CanConstProp {
584- fn visit_local ( & mut self , local : Local , context : PlaceContext , _: Location ) {
585- use rustc_middle:: mir:: visit:: PlaceContext :: * ;
586- match context {
587- // Projections are fine, because `&mut foo.x` will be caught by
588- // `MutatingUseContext::Borrow` elsewhere.
589- MutatingUse ( MutatingUseContext :: Projection )
590- // These are just stores, where the storing is not propagatable, but there may be later
591- // mutations of the same local via `Store`
592- | MutatingUse ( MutatingUseContext :: Call )
593- | MutatingUse ( MutatingUseContext :: AsmOutput )
594- | MutatingUse ( MutatingUseContext :: Deinit )
595- // Actual store that can possibly even propagate a value
596- | MutatingUse ( MutatingUseContext :: SetDiscriminant )
597- | MutatingUse ( MutatingUseContext :: Store ) => {
598- if !self . found_assignment . insert ( local) {
599- match & mut self . can_const_prop [ local] {
600- // If the local can only get propagated in its own block, then we don't have
601- // to worry about multiple assignments, as we'll nuke the const state at the
602- // end of the block anyway, and inside the block we overwrite previous
603- // states as applicable.
604- ConstPropMode :: OnlyInsideOwnBlock => { }
605- ConstPropMode :: NoPropagation => { }
606- ConstPropMode :: OnlyPropagateInto => { }
607- other @ ConstPropMode :: FullConstProp => {
608- trace ! (
609- "local {:?} can't be propagated because of multiple assignments. Previous state: {:?}" ,
610- local, other,
611- ) ;
612- * other = ConstPropMode :: OnlyInsideOwnBlock ;
613- }
614- }
615- }
616- }
617- // Reading constants is allowed an arbitrary number of times
618- NonMutatingUse ( NonMutatingUseContext :: Copy )
619- | NonMutatingUse ( NonMutatingUseContext :: Move )
620- | NonMutatingUse ( NonMutatingUseContext :: Inspect )
621- | NonMutatingUse ( NonMutatingUseContext :: Projection )
622- | NonUse ( _) => { }
623-
624- // These could be propagated with a smarter analysis or just some careful thinking about
625- // whether they'd be fine right now.
626- MutatingUse ( MutatingUseContext :: Yield )
627- | MutatingUse ( MutatingUseContext :: Drop )
628- | MutatingUse ( MutatingUseContext :: Retag )
629- // These can't ever be propagated under any scheme, as we can't reason about indirect
630- // mutation.
631- | NonMutatingUse ( NonMutatingUseContext :: SharedBorrow )
632- | NonMutatingUse ( NonMutatingUseContext :: ShallowBorrow )
633- | NonMutatingUse ( NonMutatingUseContext :: UniqueBorrow )
634- | NonMutatingUse ( NonMutatingUseContext :: AddressOf )
635- | MutatingUse ( MutatingUseContext :: Borrow )
636- | MutatingUse ( MutatingUseContext :: AddressOf ) => {
637- trace ! ( "local {:?} can't be propagaged because it's used: {:?}" , local, context) ;
638- self . can_const_prop [ local] = ConstPropMode :: NoPropagation ;
639- }
640- }
641- }
642- }
643-
644526impl < ' tcx > Visitor < ' tcx > for ConstPropagator < ' _ , ' tcx > {
645527 fn visit_body ( & mut self , body : & Body < ' tcx > ) {
646528 for ( bb, data) in body. basic_blocks ( ) . iter_enumerated ( ) {
0 commit comments