1
1
//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
2
2
3
- use rustc_errors:: { struct_span_err, Applicability } ;
3
+ use rustc_errors:: { struct_span_err, Applicability , Diagnostic } ;
4
4
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
5
5
use rustc_hir:: { self as hir, HirId , LangItem } ;
6
6
use rustc_infer:: infer:: TyCtxtInferExt ;
@@ -15,6 +15,7 @@ use rustc_span::{sym, Span, Symbol};
15
15
use rustc_trait_selection:: traits:: error_reporting:: InferCtxtExt ;
16
16
use rustc_trait_selection:: traits:: { self , TraitEngine } ;
17
17
18
+ use std:: mem;
18
19
use std:: ops:: Deref ;
19
20
20
21
use super :: ops:: { self , NonConstOp , Status } ;
@@ -181,6 +182,9 @@ pub struct Validator<'mir, 'tcx> {
181
182
span : Span ,
182
183
183
184
const_checking_stopped : bool ,
185
+
186
+ error_emitted : bool ,
187
+ secondary_errors : Vec < Diagnostic > ,
184
188
}
185
189
186
190
impl Deref for Validator < ' mir , ' tcx > {
@@ -198,6 +202,8 @@ impl Validator<'mir, 'tcx> {
198
202
ccx,
199
203
qualifs : Default :: default ( ) ,
200
204
const_checking_stopped : false ,
205
+ error_emitted : false ,
206
+ secondary_errors : Vec :: new ( ) ,
201
207
}
202
208
}
203
209
@@ -230,20 +236,20 @@ impl Validator<'mir, 'tcx> {
230
236
231
237
self . check_item_predicates ( ) ;
232
238
233
- for local in & body. local_decls {
239
+ for ( idx , local) in body. local_decls . iter_enumerated ( ) {
234
240
if local. internal {
235
241
continue ;
236
242
}
237
243
238
244
self . span = local. source_info . span ;
239
- self . check_local_or_return_ty ( local. ty ) ;
245
+ self . check_local_or_return_ty ( local. ty , idx ) ;
240
246
}
241
247
242
248
// impl trait is gone in MIR, so check the return type of a const fn by its signature
243
249
// instead of the type of the return place.
244
250
self . span = body. local_decls [ RETURN_PLACE ] . source_info . span ;
245
251
let return_ty = tcx. fn_sig ( def_id) . output ( ) ;
246
- self . check_local_or_return_ty ( return_ty. skip_binder ( ) ) ;
252
+ self . check_local_or_return_ty ( return_ty. skip_binder ( ) , RETURN_PLACE ) ;
247
253
}
248
254
249
255
self . visit_body ( & body) ;
@@ -257,6 +263,17 @@ impl Validator<'mir, 'tcx> {
257
263
let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
258
264
check_return_ty_is_sync ( tcx, & body, hir_id) ;
259
265
}
266
+
267
+ // If we got through const-checking without emitting any "primary" errors, emit any
268
+ // "secondary" errors if they occurred.
269
+ let secondary_errors = mem:: take ( & mut self . secondary_errors ) ;
270
+ if !self . error_emitted {
271
+ for error in secondary_errors {
272
+ self . tcx . sess . diagnostic ( ) . emit_diagnostic ( & error) ;
273
+ }
274
+ } else {
275
+ assert ! ( self . tcx. sess. has_errors( ) ) ;
276
+ }
260
277
}
261
278
262
279
pub fn qualifs_in_return_place ( & mut self ) -> ConstQualifs {
@@ -301,7 +318,15 @@ impl Validator<'mir, 'tcx> {
301
318
302
319
let mut err = op. build_error ( self . ccx , span) ;
303
320
assert ! ( err. is_error( ) ) ;
304
- err. emit ( ) ;
321
+
322
+ match op. importance ( ) {
323
+ ops:: DiagnosticImportance :: Primary => {
324
+ self . error_emitted = true ;
325
+ err. emit ( ) ;
326
+ }
327
+
328
+ ops:: DiagnosticImportance :: Secondary => err. buffer ( & mut self . secondary_errors ) ,
329
+ }
305
330
306
331
if O :: STOPS_CONST_CHECKING {
307
332
self . const_checking_stopped = true ;
@@ -316,7 +341,9 @@ impl Validator<'mir, 'tcx> {
316
341
self . check_op_spanned ( ops:: StaticAccess , span)
317
342
}
318
343
319
- fn check_local_or_return_ty ( & mut self , ty : Ty < ' tcx > ) {
344
+ fn check_local_or_return_ty ( & mut self , ty : Ty < ' tcx > , local : Local ) {
345
+ let kind = self . body . local_kind ( local) ;
346
+
320
347
for ty in ty. walk ( ) {
321
348
let ty = match ty. unpack ( ) {
322
349
GenericArgKind :: Type ( ty) => ty,
@@ -327,9 +354,9 @@ impl Validator<'mir, 'tcx> {
327
354
} ;
328
355
329
356
match * ty. kind ( ) {
330
- ty:: Ref ( _, _, hir:: Mutability :: Mut ) => self . check_op ( ops:: ty:: MutRef ) ,
357
+ ty:: Ref ( _, _, hir:: Mutability :: Mut ) => self . check_op ( ops:: ty:: MutRef ( kind ) ) ,
331
358
ty:: Opaque ( ..) => self . check_op ( ops:: ty:: ImplTrait ) ,
332
- ty:: FnPtr ( ..) => self . check_op ( ops:: ty:: FnPtr ) ,
359
+ ty:: FnPtr ( ..) => self . check_op ( ops:: ty:: FnPtr ( kind ) ) ,
333
360
334
361
ty:: Dynamic ( preds, _) => {
335
362
for pred in preds. iter ( ) {
0 commit comments