@@ -25,6 +25,7 @@ use syntax::feature_gate::{emit_feature_err, GateIssue};
25
25
use syntax_pos:: { Span , DUMMY_SP } ;
26
26
27
27
use std:: fmt;
28
+ use std:: ops:: Deref ;
28
29
use std:: usize;
29
30
30
31
use crate :: transform:: { MirPass , MirSource } ;
@@ -106,16 +107,16 @@ impl fmt::Display for Mode {
106
107
}
107
108
}
108
109
109
- struct Qualifier < ' a , ' tcx > {
110
+ struct ConstCx < ' a , ' tcx > {
110
111
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
111
112
param_env : ty:: ParamEnv < ' tcx > ,
112
113
mode : Mode ,
113
114
mir : & ' a Mir < ' tcx > ,
114
115
115
- local_qualif : & ' a IndexVec < Local , Qualif > ,
116
+ local_qualif : IndexVec < Local , Qualif > ,
116
117
}
117
118
118
- impl < ' a , ' tcx > Qualifier < ' a , ' tcx > {
119
+ impl < ' a , ' tcx > ConstCx < ' a , ' tcx > {
119
120
fn qualify_any_value_of_ty ( & self , ty : Ty < ' tcx > ) -> Qualif {
120
121
Qualif :: any_value_of_ty ( ty, self . tcx , self . param_env )
121
122
}
@@ -436,15 +437,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx> {
436
437
}
437
438
438
439
struct Checker < ' a , ' tcx > {
439
- tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
440
- param_env : ty:: ParamEnv < ' tcx > ,
441
- mode : Mode ,
440
+ cx : ConstCx < ' a , ' tcx > ,
441
+
442
442
span : Span ,
443
443
def_id : DefId ,
444
- mir : & ' a Mir < ' tcx > ,
445
444
rpo : ReversePostorder < ' a , ' tcx > ,
446
445
447
- local_qualif : IndexVec < Local , Qualif > ,
448
446
temp_promotion_state : IndexVec < Local , TempState > ,
449
447
promotion_candidates : Vec < Candidate > ,
450
448
}
@@ -458,6 +456,14 @@ macro_rules! unleash_miri {
458
456
} }
459
457
}
460
458
459
+ impl Deref for Checker < ' a , ' tcx > {
460
+ type Target = ConstCx < ' a , ' tcx > ;
461
+
462
+ fn deref ( & self ) -> & Self :: Target {
463
+ & self . cx
464
+ }
465
+ }
466
+
461
467
impl < ' a , ' tcx > Checker < ' a , ' tcx > {
462
468
fn new ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
463
469
def_id : DefId ,
@@ -489,29 +495,21 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
489
495
} ) . collect ( ) ;
490
496
491
497
Checker {
492
- mode,
498
+ cx : ConstCx {
499
+ tcx,
500
+ param_env,
501
+ mode,
502
+ mir,
503
+ local_qualif,
504
+ } ,
493
505
span : mir. span ,
494
506
def_id,
495
- mir,
496
507
rpo,
497
- tcx,
498
- param_env,
499
- local_qualif,
500
508
temp_promotion_state : temps,
501
509
promotion_candidates : vec ! [ ]
502
510
}
503
511
}
504
512
505
- fn qualifier ( & ' a self ) -> Qualifier < ' a , ' tcx > {
506
- Qualifier {
507
- tcx : self . tcx ,
508
- param_env : self . param_env ,
509
- mode : self . mode ,
510
- mir : self . mir ,
511
- local_qualif : & self . local_qualif ,
512
- }
513
- }
514
-
515
513
// FIXME(eddyb) we could split the errors into meaningful
516
514
// categories, but enabling full miri would make that
517
515
// slightly pointless (even with feature-gating).
@@ -545,7 +543,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
545
543
if self . mir . local_kind ( index) == LocalKind :: Temp
546
544
&& self . temp_promotion_state [ index] . is_promotable ( ) {
547
545
debug ! ( "store to promotable temp {:?} ({:?})" , index, qualif) ;
548
- let slot = & mut self . local_qualif [ index] ;
546
+ let slot = & mut self . cx . local_qualif [ index] ;
549
547
if !slot. is_empty ( ) {
550
548
span_bug ! ( self . span, "multiple assignments to {:?}" , dest) ;
551
549
}
@@ -586,20 +584,23 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
586
584
}
587
585
}
588
586
} ;
589
- debug ! ( "store to var {:?}" , index) ;
587
+
588
+ let kind = self . mir . local_kind ( index) ;
589
+ debug ! ( "store to {:?} {:?}" , kind, index) ;
590
+
590
591
// this is overly restrictive, because even full assignments do not clear the qualif
591
592
// While we could special case full assignments, this would be inconsistent with
592
593
// aggregates where we overwrite all fields via assignments, which would not get
593
594
// that feature.
594
- let slot = & mut self . local_qualif [ index] ;
595
+ let slot = & mut self . cx . local_qualif [ index] ;
595
596
* slot = * slot | qualif;
596
597
597
598
// Ensure we keep the `NOT_PROMOTABLE` flag is preserved.
598
599
// NOTE(eddyb) this is actually unnecessary right now, as
599
600
// we never replace the local's qualif (but we might in
600
601
// the future) - also, if `NOT_PROMOTABLE` only matters
601
602
// for `Mode::Fn`, then this is also pointless.
602
- if self . mir . local_kind ( index ) == LocalKind :: Temp {
603
+ if kind == LocalKind :: Temp {
603
604
if !self . temp_promotion_state [ index] . is_promotable ( ) {
604
605
* slot = * slot | Qualif :: NOT_PROMOTABLE ;
605
606
}
@@ -664,7 +665,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
664
665
// Account for errors in consts by using the
665
666
// conservative type qualification instead.
666
667
if qualif. intersects ( Qualif :: NOT_CONST ) {
667
- qualif = self . qualifier ( ) . qualify_any_value_of_ty ( mir. return_ty ( ) ) ;
668
+ qualif = self . qualify_any_value_of_ty ( mir. return_ty ( ) ) ;
668
669
}
669
670
670
671
@@ -690,7 +691,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
690
691
}
691
692
}
692
693
693
- /// Checks MIR for const-correctness, using `Qualifier `
694
+ /// Checks MIR for const-correctness, using `ConstCx `
694
695
/// for value qualifications, and accumulates writes of
695
696
/// rvalue/call results to locals, in `local_qualif`.
696
697
/// For functions (constant or not), it also records
@@ -821,7 +822,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
821
822
Operand :: Move ( ref place) => {
822
823
// Mark the consumed locals to indicate later drops are noops.
823
824
if let Place :: Local ( local) = * place {
824
- let slot = & mut self . local_qualif [ local] ;
825
+ let slot = & mut self . cx . local_qualif [ local] ;
825
826
* slot = * slot - Qualif :: NEEDS_DROP ;
826
827
}
827
828
}
@@ -960,7 +961,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
960
961
if let TerminatorKind :: Call { ref func, ref args, ref destination, .. } = * kind {
961
962
if let Some ( ( ref dest, _) ) = * destination {
962
963
let ty = dest. ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
963
- let qualif = self . qualifier ( ) . qualify_call ( func, args, ty) ;
964
+ let qualif = self . qualify_call ( func, args, ty) ;
964
965
self . assign ( dest, qualif, location) ;
965
966
}
966
967
@@ -1013,7 +1014,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
1013
1014
// stable const fns or unstable const fns
1014
1015
// with their feature gate active
1015
1016
// FIXME(eddyb) move stability checks from `is_const_fn` here.
1016
- } else if self . qualifier ( ) . is_const_panic_fn ( def_id) {
1017
+ } else if self . is_const_panic_fn ( def_id) {
1017
1018
// Check the const_panic feature gate.
1018
1019
// FIXME: cannot allow this inside `allow_internal_unstable`
1019
1020
// because that would make `panic!` insta stable in constants,
@@ -1093,7 +1094,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
1093
1094
// which happens even without the user requesting it.
1094
1095
// We can error out with a hard error if the argument is not
1095
1096
// constant here.
1096
- let arg_qualif = self . qualifier ( ) . qualify_operand ( arg) ;
1097
+ let arg_qualif = self . qualify_operand ( arg) ;
1097
1098
if ( arg_qualif - Qualif :: NOT_PROMOTABLE ) . is_empty ( ) {
1098
1099
debug ! ( "visit_terminator_kind: candidate={:?}" , candidate) ;
1099
1100
self . promotion_candidates . push ( candidate) ;
@@ -1157,7 +1158,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
1157
1158
rvalue : & Rvalue < ' tcx > ,
1158
1159
location : Location ) {
1159
1160
debug ! ( "visit_assign: dest={:?} rvalue={:?} location={:?}" , dest, rvalue, location) ;
1160
- let mut qualif = self . qualifier ( ) . qualify_rvalue ( rvalue) ;
1161
+ let mut qualif = self . qualify_rvalue ( rvalue) ;
1161
1162
1162
1163
if let Rvalue :: Ref ( _, kind, ref place) = * rvalue {
1163
1164
// Getting `MUTABLE_INTERIOR` from `qualify_rvalue` means
0 commit comments