@@ -9,7 +9,7 @@ use rustc_middle::{
9
9
} ,
10
10
ty:: { self , ParamEnv , TyCtxt } ,
11
11
} ;
12
- use rustc_span:: { def_id:: DefId , Span , DUMMY_SP } ;
12
+ use rustc_span:: def_id:: DefId ;
13
13
14
14
pub struct Validator {
15
15
/// Describes at which point in the pipeline this validation is happening.
@@ -33,18 +33,25 @@ struct TypeChecker<'a, 'tcx> {
33
33
}
34
34
35
35
impl < ' a , ' tcx > TypeChecker < ' a , ' tcx > {
36
- fn fail ( & self , span : Span , msg : impl AsRef < str > ) {
36
+ fn fail ( & self , location : Location , msg : impl AsRef < str > ) {
37
+ let span = self . body . source_info ( location) . span ;
37
38
// We use `delay_span_bug` as we might see broken MIR when other errors have already
38
39
// occurred.
39
40
self . tcx . sess . diagnostic ( ) . delay_span_bug (
40
41
span,
41
- & format ! ( "broken MIR in {:?} ({}): {}" , self . def_id, self . when, msg. as_ref( ) ) ,
42
+ & format ! (
43
+ "broken MIR in {:?} ({}) at {:?}:\n {}" ,
44
+ self . def_id,
45
+ self . when,
46
+ location,
47
+ msg. as_ref( )
48
+ ) ,
42
49
) ;
43
50
}
44
51
45
- fn check_bb ( & self , span : Span , bb : BasicBlock ) {
52
+ fn check_bb ( & self , location : Location , bb : BasicBlock ) {
46
53
if self . body . basic_blocks ( ) . get ( bb) . is_none ( ) {
47
- self . fail ( span , format ! ( "encountered jump to invalid basic block {:?}" , bb) )
54
+ self . fail ( location , format ! ( "encountered jump to invalid basic block {:?}" , bb) )
48
55
}
49
56
}
50
57
}
@@ -57,7 +64,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
57
64
let span = self . body . source_info ( location) . span ;
58
65
59
66
if !ty. is_copy_modulo_regions ( self . tcx , self . param_env , span) {
60
- self . fail ( span , format ! ( "`Operand::Copy` with non-`Copy` type {}" , ty) ) ;
67
+ self . fail ( location , format ! ( "`Operand::Copy` with non-`Copy` type {}" , ty) ) ;
61
68
}
62
69
}
63
70
@@ -72,11 +79,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
72
79
Rvalue :: Use ( Operand :: Copy ( src) | Operand :: Move ( src) ) => {
73
80
if dest == src {
74
81
self . fail (
75
- DUMMY_SP ,
76
- format ! (
77
- "encountered `Assign` statement with overlapping memory at {:?}" ,
78
- location
79
- ) ,
82
+ location,
83
+ "encountered `Assign` statement with overlapping memory" ,
80
84
) ;
81
85
}
82
86
}
@@ -85,15 +89,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
85
89
}
86
90
}
87
91
88
- fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , _location : Location ) {
92
+ fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
89
93
match & terminator. kind {
90
94
TerminatorKind :: Goto { target } => {
91
- self . check_bb ( terminator . source_info . span , * target) ;
95
+ self . check_bb ( location , * target) ;
92
96
}
93
97
TerminatorKind :: SwitchInt { targets, values, .. } => {
94
98
if targets. len ( ) != values. len ( ) + 1 {
95
99
self . fail (
96
- terminator . source_info . span ,
100
+ location ,
97
101
format ! (
98
102
"encountered `SwitchInt` terminator with {} values, but {} targets (should be values+1)" ,
99
103
values. len( ) ,
@@ -102,72 +106,72 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
102
106
) ;
103
107
}
104
108
for target in targets {
105
- self . check_bb ( terminator . source_info . span , * target) ;
109
+ self . check_bb ( location , * target) ;
106
110
}
107
111
}
108
112
TerminatorKind :: Drop { target, unwind, .. } => {
109
- self . check_bb ( terminator . source_info . span , * target) ;
113
+ self . check_bb ( location , * target) ;
110
114
if let Some ( unwind) = unwind {
111
- self . check_bb ( terminator . source_info . span , * unwind) ;
115
+ self . check_bb ( location , * unwind) ;
112
116
}
113
117
}
114
118
TerminatorKind :: DropAndReplace { target, unwind, .. } => {
115
- self . check_bb ( terminator . source_info . span , * target) ;
119
+ self . check_bb ( location , * target) ;
116
120
if let Some ( unwind) = unwind {
117
- self . check_bb ( terminator . source_info . span , * unwind) ;
121
+ self . check_bb ( location , * unwind) ;
118
122
}
119
123
}
120
124
TerminatorKind :: Call { func, destination, cleanup, .. } => {
121
125
let func_ty = func. ty ( & self . body . local_decls , self . tcx ) ;
122
126
match func_ty. kind {
123
127
ty:: FnPtr ( ..) | ty:: FnDef ( ..) => { }
124
128
_ => self . fail (
125
- terminator . source_info . span ,
129
+ location ,
126
130
format ! ( "encountered non-callable type {} in `Call` terminator" , func_ty) ,
127
131
) ,
128
132
}
129
133
if let Some ( ( _, target) ) = destination {
130
- self . check_bb ( terminator . source_info . span , * target) ;
134
+ self . check_bb ( location , * target) ;
131
135
}
132
136
if let Some ( cleanup) = cleanup {
133
- self . check_bb ( terminator . source_info . span , * cleanup) ;
137
+ self . check_bb ( location , * cleanup) ;
134
138
}
135
139
}
136
140
TerminatorKind :: Assert { cond, target, cleanup, .. } => {
137
141
let cond_ty = cond. ty ( & self . body . local_decls , self . tcx ) ;
138
142
if cond_ty != self . tcx . types . bool {
139
143
self . fail (
140
- terminator . source_info . span ,
144
+ location ,
141
145
format ! (
142
146
"encountered non-boolean condition of type {} in `Assert` terminator" ,
143
147
cond_ty
144
148
) ,
145
149
) ;
146
150
}
147
- self . check_bb ( terminator . source_info . span , * target) ;
151
+ self . check_bb ( location , * target) ;
148
152
if let Some ( cleanup) = cleanup {
149
- self . check_bb ( terminator . source_info . span , * cleanup) ;
153
+ self . check_bb ( location , * cleanup) ;
150
154
}
151
155
}
152
156
TerminatorKind :: Yield { resume, drop, .. } => {
153
- self . check_bb ( terminator . source_info . span , * resume) ;
157
+ self . check_bb ( location , * resume) ;
154
158
if let Some ( drop) = drop {
155
- self . check_bb ( terminator . source_info . span , * drop) ;
159
+ self . check_bb ( location , * drop) ;
156
160
}
157
161
}
158
162
TerminatorKind :: FalseEdges { real_target, imaginary_target } => {
159
- self . check_bb ( terminator . source_info . span , * real_target) ;
160
- self . check_bb ( terminator . source_info . span , * imaginary_target) ;
163
+ self . check_bb ( location , * real_target) ;
164
+ self . check_bb ( location , * imaginary_target) ;
161
165
}
162
166
TerminatorKind :: FalseUnwind { real_target, unwind } => {
163
- self . check_bb ( terminator . source_info . span , * real_target) ;
167
+ self . check_bb ( location , * real_target) ;
164
168
if let Some ( unwind) = unwind {
165
- self . check_bb ( terminator . source_info . span , * unwind) ;
169
+ self . check_bb ( location , * unwind) ;
166
170
}
167
171
}
168
172
TerminatorKind :: InlineAsm { destination, .. } => {
169
173
if let Some ( destination) = destination {
170
- self . check_bb ( terminator . source_info . span , * destination) ;
174
+ self . check_bb ( location , * destination) ;
171
175
}
172
176
}
173
177
// Nothing to validate for these.
0 commit comments