@@ -7,11 +7,9 @@ use crate::ty::query::TyCtxtAt;
77use crate :: ty:: { self , layout, Ty } ;
88
99use backtrace:: Backtrace ;
10- use hir:: GeneratorKind ;
1110use rustc_errors:: { struct_span_err, DiagnosticBuilder } ;
1211use rustc_hir as hir;
1312use rustc_macros:: HashStable ;
14- use rustc_span:: symbol:: Symbol ;
1513use rustc_span:: { Pos , Span } ;
1614use rustc_target:: spec:: abi:: Abi ;
1715use std:: { any:: Any , env, fmt} ;
@@ -128,9 +126,15 @@ impl<'tcx> ConstEvalErr<'tcx> {
128126 }
129127 }
130128
131- /// Sets the message passed in via `message` and adds span labels before handing control back
132- /// to `emit` to do any final processing. It's the caller's responsibility to call emit(),
133- /// stash(), etc. within the `emit` function to dispose of the diagnostic properly.
129+ /// Create a diagnostic for this const eval error.
130+ ///
131+ /// Sets the message passed in via `message` and adds span labels with detailed error
132+ /// information before handing control back to `emit` to do any final processing.
133+ /// It's the caller's responsibility to call emit(), stash(), etc. within the `emit`
134+ /// function to dispose of the diagnostic properly.
135+ ///
136+ /// If `lint_root.is_some()` report it as a lint, else report it as a hard error.
137+ /// (Except that for some errors, we ignore all that -- see `must_error` below.)
134138 fn struct_generic (
135139 & self ,
136140 tcx : TyCtxtAt < ' tcx > ,
@@ -139,20 +143,30 @@ impl<'tcx> ConstEvalErr<'tcx> {
139143 lint_root : Option < hir:: HirId > ,
140144 ) -> Result < ( ) , ErrorHandled > {
141145 let must_error = match self . error {
142- InterpError :: MachineStop ( _) => bug ! ( "CTFE does not stop" ) ,
143146 err_inval ! ( Layout ( LayoutError :: Unknown ( _) ) ) | err_inval ! ( TooGeneric ) => {
144147 return Err ( ErrorHandled :: TooGeneric ) ;
145148 }
146149 err_inval ! ( TypeckError ) => return Err ( ErrorHandled :: Reported ) ,
150+ // We must *always* hard error on these, even if the caller wants just a lint.
147151 err_inval ! ( Layout ( LayoutError :: SizeOverflow ( _) ) ) => true ,
148152 _ => false ,
149153 } ;
150154 trace ! ( "reporting const eval failure at {:?}" , self . span) ;
151155
152- let add_span_labels = |err : & mut DiagnosticBuilder < ' _ > | {
153- if !must_error {
154- err. span_label ( self . span , self . error . to_string ( ) ) ;
156+ let err_msg = match & self . error {
157+ InterpError :: MachineStop ( msg) => {
158+ // A custom error (`ConstEvalErrKind` in `librustc_mir/interp/const_eval/error.rs`).
159+ // Should be turned into a string by now.
160+ msg. downcast_ref :: < String > ( ) . expect ( "invalid MachineStop payload" ) . clone ( )
155161 }
162+ err => err. to_string ( ) ,
163+ } ;
164+
165+ let finish = |mut err : DiagnosticBuilder < ' _ > , span_msg : Option < String > | {
166+ if let Some ( span_msg) = span_msg {
167+ err. span_label ( self . span , span_msg) ;
168+ }
169+ // Add spans for the stacktrace.
156170 // Skip the last, which is just the environment of the constant. The stacktrace
157171 // is sometimes empty because we create "fake" eval contexts in CTFE to do work
158172 // on constant values.
@@ -161,35 +175,37 @@ impl<'tcx> ConstEvalErr<'tcx> {
161175 err. span_label ( frame_info. call_site , frame_info. to_string ( ) ) ;
162176 }
163177 }
178+ // Let the caller finish the job.
179+ emit ( err)
164180 } ;
165181
166- if let ( Some ( lint_root) , false ) = ( lint_root, must_error) {
167- let hir_id = self
168- . stacktrace
169- . iter ( )
170- . rev ( )
171- . filter_map ( |frame| frame. lint_root )
172- . next ( )
173- . unwrap_or ( lint_root) ;
174- tcx. struct_span_lint_hir (
175- rustc_session:: lint:: builtin:: CONST_ERR ,
176- hir_id,
177- tcx. span ,
178- |lint| {
179- let mut err = lint. build ( message) ;
180- add_span_labels ( & mut err) ;
181- emit ( err) ;
182- } ,
183- ) ;
182+ if must_error {
183+ // The `message` makes little sense here, this is a more serious error than the
184+ // caller thinks anyway.
185+ // See <https://github.com/rust-lang/rust/pull/63152>.
186+ finish ( struct_error ( tcx, & err_msg) , None ) ;
184187 } else {
185- let mut err = if must_error {
186- struct_error ( tcx, & self . error . to_string ( ) )
188+ // Regular case.
189+ if let Some ( lint_root) = lint_root {
190+ // Report as lint.
191+ let hir_id = self
192+ . stacktrace
193+ . iter ( )
194+ . rev ( )
195+ . filter_map ( |frame| frame. lint_root )
196+ . next ( )
197+ . unwrap_or ( lint_root) ;
198+ tcx. struct_span_lint_hir (
199+ rustc_session:: lint:: builtin:: CONST_ERR ,
200+ hir_id,
201+ tcx. span ,
202+ |lint| finish ( lint. build ( message) , Some ( err_msg) ) ,
203+ ) ;
187204 } else {
188- struct_error ( tcx, message)
189- } ;
190- add_span_labels ( & mut err) ;
191- emit ( err) ;
192- } ;
205+ // Report as hard error.
206+ finish ( struct_error ( tcx, message) , Some ( err_msg) ) ;
207+ }
208+ }
193209 Ok ( ( ) )
194210 }
195211}
@@ -259,63 +275,6 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
259275 }
260276}
261277
262- #[ derive( Clone , RustcEncodable , RustcDecodable , HashStable , PartialEq ) ]
263- pub enum PanicInfo < O > {
264- Panic { msg : Symbol , line : u32 , col : u32 , file : Symbol } ,
265- BoundsCheck { len : O , index : O } ,
266- Overflow ( mir:: BinOp ) ,
267- OverflowNeg ,
268- DivisionByZero ,
269- RemainderByZero ,
270- ResumedAfterReturn ( GeneratorKind ) ,
271- ResumedAfterPanic ( GeneratorKind ) ,
272- }
273-
274- /// Type for MIR `Assert` terminator error messages.
275- pub type AssertMessage < ' tcx > = PanicInfo < mir:: Operand < ' tcx > > ;
276-
277- impl < O > PanicInfo < O > {
278- /// Getting a description does not require `O` to be printable, and does not
279- /// require allocation.
280- /// The caller is expected to handle `Panic` and `BoundsCheck` separately.
281- pub fn description ( & self ) -> & ' static str {
282- use PanicInfo :: * ;
283- match self {
284- Overflow ( mir:: BinOp :: Add ) => "attempt to add with overflow" ,
285- Overflow ( mir:: BinOp :: Sub ) => "attempt to subtract with overflow" ,
286- Overflow ( mir:: BinOp :: Mul ) => "attempt to multiply with overflow" ,
287- Overflow ( mir:: BinOp :: Div ) => "attempt to divide with overflow" ,
288- Overflow ( mir:: BinOp :: Rem ) => "attempt to calculate the remainder with overflow" ,
289- OverflowNeg => "attempt to negate with overflow" ,
290- Overflow ( mir:: BinOp :: Shr ) => "attempt to shift right with overflow" ,
291- Overflow ( mir:: BinOp :: Shl ) => "attempt to shift left with overflow" ,
292- Overflow ( op) => bug ! ( "{:?} cannot overflow" , op) ,
293- DivisionByZero => "attempt to divide by zero" ,
294- RemainderByZero => "attempt to calculate the remainder with a divisor of zero" ,
295- ResumedAfterReturn ( GeneratorKind :: Gen ) => "generator resumed after completion" ,
296- ResumedAfterReturn ( GeneratorKind :: Async ( _) ) => "`async fn` resumed after completion" ,
297- ResumedAfterPanic ( GeneratorKind :: Gen ) => "generator resumed after panicking" ,
298- ResumedAfterPanic ( GeneratorKind :: Async ( _) ) => "`async fn` resumed after panicking" ,
299- Panic { .. } | BoundsCheck { .. } => bug ! ( "Unexpected PanicInfo" ) ,
300- }
301- }
302- }
303-
304- impl < O : fmt:: Debug > fmt:: Debug for PanicInfo < O > {
305- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
306- use PanicInfo :: * ;
307- match self {
308- Panic { ref msg, line, col, ref file } => {
309- write ! ( f, "the evaluated program panicked at '{}', {}:{}:{}" , msg, file, line, col)
310- }
311- BoundsCheck { ref len, ref index } => {
312- write ! ( f, "index out of bounds: the len is {:?} but the index is {:?}" , len, index)
313- }
314- _ => write ! ( f, "{}" , self . description( ) ) ,
315- }
316- }
317- }
318-
319278/// Error information for when the program we executed turned out not to actually be a valid
320279/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
321280/// where we work on generic code or execution does not have all information available.
@@ -616,8 +575,6 @@ impl fmt::Debug for ResourceExhaustionInfo {
616575}
617576
618577pub enum InterpError < ' tcx > {
619- /// The program panicked.
620- Panic ( PanicInfo < u64 > ) ,
621578 /// The program caused undefined behavior.
622579 UndefinedBehavior ( UndefinedBehaviorInfo ) ,
623580 /// The program did something the interpreter does not support (some of these *might* be UB
@@ -650,8 +607,7 @@ impl fmt::Debug for InterpError<'_> {
650607 InvalidProgram ( ref msg) => write ! ( f, "{:?}" , msg) ,
651608 UndefinedBehavior ( ref msg) => write ! ( f, "{:?}" , msg) ,
652609 ResourceExhaustion ( ref msg) => write ! ( f, "{:?}" , msg) ,
653- Panic ( ref msg) => write ! ( f, "{:?}" , msg) ,
654- MachineStop ( _) => write ! ( f, "machine caused execution to stop" ) ,
610+ MachineStop ( _) => bug ! ( "unhandled MachineStop" ) ,
655611 }
656612 }
657613}
0 commit comments