1
1
//! Propagates constants for early reporting of statically known
2
2
//! assertion failures
3
3
4
+ use crate :: const_prop:: CanConstProp ;
4
5
use crate :: const_prop:: ConstPropMachine ;
5
6
use crate :: const_prop:: ConstPropMode ;
6
7
use crate :: MirLint ;
@@ -13,11 +14,11 @@ use rustc_hir::def::DefKind;
13
14
use rustc_hir:: HirId ;
14
15
use rustc_index:: bit_set:: BitSet ;
15
16
use rustc_index:: vec:: IndexVec ;
16
- use rustc_middle:: mir:: visit:: { MutatingUseContext , NonMutatingUseContext , PlaceContext , Visitor } ;
17
+ use rustc_middle:: mir:: visit:: Visitor ;
17
18
use 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 ,
21
22
} ;
22
23
use rustc_middle:: ty:: layout:: { LayoutError , LayoutOf , LayoutOfHelpers , TyAndLayout } ;
23
24
use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
@@ -522,125 +523,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
522
523
}
523
524
}
524
525
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
-
644
526
impl < ' tcx > Visitor < ' tcx > for ConstPropagator < ' _ , ' tcx > {
645
527
fn visit_body ( & mut self , body : & Body < ' tcx > ) {
646
528
for ( bb, data) in body. basic_blocks ( ) . iter_enumerated ( ) {
0 commit comments