11//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
22
3- use rustc_errors:: { struct_span_err, Applicability } ;
3+ use rustc_errors:: { struct_span_err, Applicability , Diagnostic } ;
44use rustc_hir:: def_id:: { DefId , LocalDefId } ;
55use rustc_hir:: { self as hir, HirId , LangItem } ;
66use rustc_infer:: infer:: TyCtxtInferExt ;
@@ -15,6 +15,7 @@ use rustc_span::{sym, Span, Symbol};
1515use rustc_trait_selection:: traits:: error_reporting:: InferCtxtExt ;
1616use rustc_trait_selection:: traits:: { self , TraitEngine } ;
1717
18+ use std:: mem;
1819use std:: ops:: Deref ;
1920
2021use super :: ops:: { self , NonConstOp , Status } ;
@@ -181,6 +182,9 @@ pub struct Validator<'mir, 'tcx> {
181182 span : Span ,
182183
183184 const_checking_stopped : bool ,
185+
186+ error_emitted : bool ,
187+ secondary_errors : Vec < Diagnostic > ,
184188}
185189
186190impl Deref for Validator < ' mir , ' tcx > {
@@ -198,6 +202,8 @@ impl Validator<'mir, 'tcx> {
198202 ccx,
199203 qualifs : Default :: default ( ) ,
200204 const_checking_stopped : false ,
205+ error_emitted : false ,
206+ secondary_errors : Vec :: new ( ) ,
201207 }
202208 }
203209
@@ -230,20 +236,20 @@ impl Validator<'mir, 'tcx> {
230236
231237 self . check_item_predicates ( ) ;
232238
233- for local in & body. local_decls {
239+ for ( idx , local) in body. local_decls . iter_enumerated ( ) {
234240 if local. internal {
235241 continue ;
236242 }
237243
238244 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 ) ;
240246 }
241247
242248 // impl trait is gone in MIR, so check the return type of a const fn by its signature
243249 // instead of the type of the return place.
244250 self . span = body. local_decls [ RETURN_PLACE ] . source_info . span ;
245251 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 ) ;
247253 }
248254
249255 self . visit_body ( & body) ;
@@ -257,6 +263,17 @@ impl Validator<'mir, 'tcx> {
257263 let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
258264 check_return_ty_is_sync ( tcx, & body, hir_id) ;
259265 }
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+ }
260277 }
261278
262279 pub fn qualifs_in_return_place ( & mut self ) -> ConstQualifs {
@@ -301,7 +318,15 @@ impl Validator<'mir, 'tcx> {
301318
302319 let mut err = op. build_error ( self . ccx , span) ;
303320 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+ }
305330
306331 if O :: STOPS_CONST_CHECKING {
307332 self . const_checking_stopped = true ;
@@ -316,7 +341,9 @@ impl Validator<'mir, 'tcx> {
316341 self . check_op_spanned ( ops:: StaticAccess , span)
317342 }
318343
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+
320347 for ty in ty. walk ( ) {
321348 let ty = match ty. unpack ( ) {
322349 GenericArgKind :: Type ( ty) => ty,
@@ -327,9 +354,9 @@ impl Validator<'mir, 'tcx> {
327354 } ;
328355
329356 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 ) ) ,
331358 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 ) ) ,
333360
334361 ty:: Dynamic ( preds, _) => {
335362 for pred in preds. iter ( ) {
0 commit comments