@@ -72,8 +72,9 @@ impl<'tcx> MirPass<'tcx> for Validator {
72
72
cfg_checker. visit_body ( body) ;
73
73
cfg_checker. check_cleanup_control_flow ( ) ;
74
74
75
- let mut type_checker = TypeChecker { when : & self . when , body, tcx, param_env, mir_phase } ;
76
- type_checker. visit_body ( body) ;
75
+ for ( location, msg) in validate_types ( tcx, self . mir_phase , param_env, body) {
76
+ cfg_checker. fail ( location, msg) ;
77
+ }
77
78
78
79
if let MirPhase :: Runtime ( _) = body. phase {
79
80
if let ty:: InstanceDef :: Item ( _) = body. source . instance {
@@ -498,30 +499,28 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
498
499
}
499
500
}
500
501
502
+ fn validate_types < ' tcx > (
503
+ tcx : TyCtxt < ' tcx > ,
504
+ mir_phase : MirPhase ,
505
+ param_env : ty:: ParamEnv < ' tcx > ,
506
+ body : & Body < ' tcx > ,
507
+ ) -> Vec < ( Location , String ) > {
508
+ let mut type_checker = TypeChecker { body, tcx, param_env, mir_phase, failures : Vec :: new ( ) } ;
509
+ type_checker. visit_body ( body) ;
510
+ type_checker. failures
511
+ }
512
+
501
513
struct TypeChecker < ' a , ' tcx > {
502
- when : & ' a str ,
503
514
body : & ' a Body < ' tcx > ,
504
515
tcx : TyCtxt < ' tcx > ,
505
516
param_env : ParamEnv < ' tcx > ,
506
517
mir_phase : MirPhase ,
518
+ failures : Vec < ( Location , String ) > ,
507
519
}
508
520
509
521
impl < ' a , ' tcx > TypeChecker < ' a , ' tcx > {
510
- #[ track_caller]
511
- fn fail ( & self , location : Location , msg : impl AsRef < str > ) {
512
- let span = self . body . source_info ( location) . span ;
513
- // We use `delay_span_bug` as we might see broken MIR when other errors have already
514
- // occurred.
515
- self . tcx . sess . diagnostic ( ) . delay_span_bug (
516
- span,
517
- format ! (
518
- "broken MIR in {:?} ({}) at {:?}:\n {}" ,
519
- self . body. source. instance,
520
- self . when,
521
- location,
522
- msg. as_ref( )
523
- ) ,
524
- ) ;
522
+ fn fail ( & mut self , location : Location , msg : impl Into < String > ) {
523
+ self . failures . push ( ( location, msg. into ( ) ) ) ;
525
524
}
526
525
527
526
/// Check if src can be assigned into dest.
@@ -593,10 +592,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
593
592
}
594
593
ProjectionElem :: Field ( f, ty) => {
595
594
let parent_ty = place_ref. ty ( & self . body . local_decls , self . tcx ) ;
596
- let fail_out_of_bounds = |this : & Self , location| {
595
+ let fail_out_of_bounds = |this : & mut Self , location| {
597
596
this. fail ( location, format ! ( "Out of bounds field {:?} for {:?}" , f, parent_ty) ) ;
598
597
} ;
599
- let check_equal = |this : & Self , location, f_ty| {
598
+ let check_equal = |this : & mut Self , location, f_ty| {
600
599
if !this. mir_assign_valid_types ( ty, f_ty) {
601
600
this. fail (
602
601
location,
@@ -691,9 +690,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
691
690
}
692
691
693
692
fn visit_var_debug_info ( & mut self , debuginfo : & VarDebugInfo < ' tcx > ) {
694
- let check_place = |place : Place < ' _ > | {
693
+ let check_place = |this : & mut Self , place : Place < ' _ > | {
695
694
if place. projection . iter ( ) . any ( |p| !p. can_use_in_debuginfo ( ) ) {
696
- self . fail (
695
+ this . fail (
697
696
START_BLOCK . start_location ( ) ,
698
697
format ! ( "illegal place {:?} in debuginfo for {:?}" , place, debuginfo. name) ,
699
698
) ;
@@ -702,7 +701,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
702
701
match debuginfo. value {
703
702
VarDebugInfoContents :: Const ( _) => { }
704
703
VarDebugInfoContents :: Place ( place) => {
705
- check_place ( place) ;
704
+ check_place ( self , place) ;
706
705
if debuginfo. references != 0 && place. projection . last ( ) == Some ( & PlaceElem :: Deref ) {
707
706
self . fail (
708
707
START_BLOCK . start_location ( ) ,
@@ -712,7 +711,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
712
711
}
713
712
VarDebugInfoContents :: Composite { ty, ref fragments } => {
714
713
for f in fragments {
715
- check_place ( f. contents ) ;
714
+ check_place ( self , f. contents ) ;
716
715
if ty. is_union ( ) || ty. is_enum ( ) {
717
716
self . fail (
718
717
START_BLOCK . start_location ( ) ,
@@ -969,7 +968,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
969
968
}
970
969
}
971
970
Rvalue :: NullaryOp ( NullOp :: OffsetOf ( fields) , container) => {
972
- let fail_out_of_bounds = |this : & Self , location, field, ty| {
971
+ let fail_out_of_bounds = |this : & mut Self , location, field, ty| {
973
972
this. fail ( location, format ! ( "Out of bounds field {field:?} for {ty:?}" ) ) ;
974
973
} ;
975
974
0 commit comments