@@ -7,11 +7,9 @@ use crate::ty::query::TyCtxtAt;
7
7
use crate :: ty:: { self , layout, Ty } ;
8
8
9
9
use backtrace:: Backtrace ;
10
- use hir:: GeneratorKind ;
11
10
use rustc_errors:: { struct_span_err, DiagnosticBuilder } ;
12
11
use rustc_hir as hir;
13
12
use rustc_macros:: HashStable ;
14
- use rustc_span:: symbol:: Symbol ;
15
13
use rustc_span:: { Pos , Span } ;
16
14
use rustc_target:: spec:: abi:: Abi ;
17
15
use std:: { any:: Any , env, fmt} ;
@@ -128,9 +126,15 @@ impl<'tcx> ConstEvalErr<'tcx> {
128
126
}
129
127
}
130
128
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.)
134
138
fn struct_generic (
135
139
& self ,
136
140
tcx : TyCtxtAt < ' tcx > ,
@@ -139,20 +143,30 @@ impl<'tcx> ConstEvalErr<'tcx> {
139
143
lint_root : Option < hir:: HirId > ,
140
144
) -> Result < ( ) , ErrorHandled > {
141
145
let must_error = match self . error {
142
- InterpError :: MachineStop ( _) => bug ! ( "CTFE does not stop" ) ,
143
146
err_inval ! ( Layout ( LayoutError :: Unknown ( _) ) ) | err_inval ! ( TooGeneric ) => {
144
147
return Err ( ErrorHandled :: TooGeneric ) ;
145
148
}
146
149
err_inval ! ( TypeckError ) => return Err ( ErrorHandled :: Reported ) ,
150
+ // We must *always* hard error on these, even if the caller wants just a lint.
147
151
err_inval ! ( Layout ( LayoutError :: SizeOverflow ( _) ) ) => true ,
148
152
_ => false ,
149
153
} ;
150
154
trace ! ( "reporting const eval failure at {:?}" , self . span) ;
151
155
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 ( )
155
161
}
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.
156
170
// Skip the last, which is just the environment of the constant. The stacktrace
157
171
// is sometimes empty because we create "fake" eval contexts in CTFE to do work
158
172
// on constant values.
@@ -161,35 +175,37 @@ impl<'tcx> ConstEvalErr<'tcx> {
161
175
err. span_label ( frame_info. call_site , frame_info. to_string ( ) ) ;
162
176
}
163
177
}
178
+ // Let the caller finish the job.
179
+ emit ( err)
164
180
} ;
165
181
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 ) ;
184
187
} 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
+ ) ;
187
204
} 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
+ }
193
209
Ok ( ( ) )
194
210
}
195
211
}
@@ -259,63 +275,6 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
259
275
}
260
276
}
261
277
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
-
319
278
/// Error information for when the program we executed turned out not to actually be a valid
320
279
/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
321
280
/// where we work on generic code or execution does not have all information available.
@@ -616,8 +575,6 @@ impl fmt::Debug for ResourceExhaustionInfo {
616
575
}
617
576
618
577
pub enum InterpError < ' tcx > {
619
- /// The program panicked.
620
- Panic ( PanicInfo < u64 > ) ,
621
578
/// The program caused undefined behavior.
622
579
UndefinedBehavior ( UndefinedBehaviorInfo ) ,
623
580
/// The program did something the interpreter does not support (some of these *might* be UB
@@ -650,8 +607,7 @@ impl fmt::Debug for InterpError<'_> {
650
607
InvalidProgram ( ref msg) => write ! ( f, "{:?}" , msg) ,
651
608
UndefinedBehavior ( ref msg) => write ! ( f, "{:?}" , msg) ,
652
609
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" ) ,
655
611
}
656
612
}
657
613
}
0 commit comments