@@ -72,8 +72,9 @@ impl<'tcx> MirPass<'tcx> for Validator {
7272 cfg_checker. visit_body ( body) ;
7373 cfg_checker. check_cleanup_control_flow ( ) ;
7474
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+ }
7778
7879 if let MirPhase :: Runtime ( _) = body. phase {
7980 if let ty:: InstanceDef :: Item ( _) = body. source . instance {
@@ -498,30 +499,28 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
498499 }
499500}
500501
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+
501513struct TypeChecker < ' a , ' tcx > {
502- when : & ' a str ,
503514 body : & ' a Body < ' tcx > ,
504515 tcx : TyCtxt < ' tcx > ,
505516 param_env : ParamEnv < ' tcx > ,
506517 mir_phase : MirPhase ,
518+ failures : Vec < ( Location , String ) > ,
507519}
508520
509521impl < ' 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 ( ) ) ) ;
525524 }
526525
527526 /// Check if src can be assigned into dest.
@@ -593,10 +592,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
593592 }
594593 ProjectionElem :: Field ( f, ty) => {
595594 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| {
597596 this. fail ( location, format ! ( "Out of bounds field {:?} for {:?}" , f, parent_ty) ) ;
598597 } ;
599- let check_equal = |this : & Self , location, f_ty| {
598+ let check_equal = |this : & mut Self , location, f_ty| {
600599 if !this. mir_assign_valid_types ( ty, f_ty) {
601600 this. fail (
602601 location,
@@ -691,9 +690,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
691690 }
692691
693692 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 < ' _ > | {
695694 if place. projection . iter ( ) . any ( |p| !p. can_use_in_debuginfo ( ) ) {
696- self . fail (
695+ this . fail (
697696 START_BLOCK . start_location ( ) ,
698697 format ! ( "illegal place {:?} in debuginfo for {:?}" , place, debuginfo. name) ,
699698 ) ;
@@ -702,7 +701,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
702701 match debuginfo. value {
703702 VarDebugInfoContents :: Const ( _) => { }
704703 VarDebugInfoContents :: Place ( place) => {
705- check_place ( place) ;
704+ check_place ( self , place) ;
706705 if debuginfo. references != 0 && place. projection . last ( ) == Some ( & PlaceElem :: Deref ) {
707706 self . fail (
708707 START_BLOCK . start_location ( ) ,
@@ -712,7 +711,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
712711 }
713712 VarDebugInfoContents :: Composite { ty, ref fragments } => {
714713 for f in fragments {
715- check_place ( f. contents ) ;
714+ check_place ( self , f. contents ) ;
716715 if ty. is_union ( ) || ty. is_enum ( ) {
717716 self . fail (
718717 START_BLOCK . start_location ( ) ,
@@ -969,7 +968,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
969968 }
970969 }
971970 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| {
973972 this. fail ( location, format ! ( "Out of bounds field {field:?} for {ty:?}" ) ) ;
974973 } ;
975974
0 commit comments