@@ -9,10 +9,11 @@ use std::hash::Hash;
99use rustc_data_structures:: fx:: FxHashMap ;
1010
1111use rustc_span:: source_map:: Span ;
12+ use rustc_span:: symbol:: Symbol ;
1213
1314use crate :: interpret:: {
1415 self , snapshot, AllocId , Allocation , AssertMessage , GlobalId , ImmTy , InterpCx , InterpResult ,
15- Memory , MemoryKind , OpTy , PlaceTy , Pointer , Scalar ,
16+ Memory , MemoryKind , OpTy , PanicInfo , PlaceTy , Pointer , Scalar ,
1617} ;
1718
1819use super :: error:: * ;
@@ -56,6 +57,32 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
5657 self . dump_place ( * dest) ;
5758 return Ok ( true ) ;
5859 }
60+
61+ /// "Intercept" a function call to a panic-related function
62+ /// because we have something special to do for it.
63+ /// Returns `true` if an intercept happened.
64+ pub fn hook_panic_fn (
65+ & mut self ,
66+ span : Span ,
67+ instance : ty:: Instance < ' tcx > ,
68+ args : & [ OpTy < ' tcx > ] ,
69+ ) -> InterpResult < ' tcx , bool > {
70+ let def_id = instance. def_id ( ) ;
71+ if Some ( def_id) == self . tcx . lang_items ( ) . panic_fn ( )
72+ || Some ( def_id) == self . tcx . lang_items ( ) . begin_panic_fn ( )
73+ {
74+ // &'static str
75+ assert ! ( args. len( ) == 1 ) ;
76+
77+ let msg_place = self . deref_operand ( args[ 0 ] ) ?;
78+ let msg = Symbol :: intern ( self . read_str ( msg_place) ?) ;
79+ let span = self . find_closest_untracked_caller_location ( ) . unwrap_or ( span) ;
80+ let ( file, line, col) = self . location_triple_for_span ( span) ;
81+ Err ( ConstEvalErrKind :: Panic ( PanicInfo :: Panic { msg, file, line, col } ) . into ( ) )
82+ } else {
83+ Ok ( false )
84+ }
85+ }
5986}
6087
6188/// Number of steps until the detector even starts doing anything.
@@ -212,7 +239,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
212239 Ok ( body) => * body,
213240 Err ( err) => {
214241 if let err_unsup ! ( NoMirFor ( ref path) ) = err. kind {
215- return Err ( ConstEvalError :: NeedsRfc ( format ! (
242+ return Err ( ConstEvalErrKind :: NeedsRfc ( format ! (
216243 "calling extern function `{}`" ,
217244 path
218245 ) )
@@ -246,7 +273,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
246273 }
247274 // An intrinsic that we do not support
248275 let intrinsic_name = ecx. tcx . item_name ( instance. def_id ( ) ) ;
249- Err ( ConstEvalError :: NeedsRfc ( format ! ( "calling intrinsic `{}`" , intrinsic_name) ) . into ( ) )
276+ Err ( ConstEvalErrKind :: NeedsRfc ( format ! ( "calling intrinsic `{}`" , intrinsic_name) ) . into ( ) )
250277 }
251278
252279 fn assert_panic (
@@ -256,7 +283,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
256283 _unwind : Option < mir:: BasicBlock > ,
257284 ) -> InterpResult < ' tcx > {
258285 use rustc:: mir:: interpret:: PanicInfo :: * ;
259- Err ( match msg {
286+ // Convert `PanicInfo<Operand>` to `PanicInfo<u64>`.
287+ let err = match msg {
260288 BoundsCheck { ref len, ref index } => {
261289 let len = ecx
262290 . read_immediate ( ecx. eval_operand ( len, None ) ?)
@@ -268,21 +296,21 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
268296 . expect ( "can't eval index" )
269297 . to_scalar ( ) ?
270298 . to_machine_usize ( & * ecx) ?;
271- err_panic ! ( BoundsCheck { len, index } )
299+ BoundsCheck { len, index }
272300 }
273- Overflow ( op) => err_panic ! ( Overflow ( * op) ) ,
274- OverflowNeg => err_panic ! ( OverflowNeg ) ,
275- DivisionByZero => err_panic ! ( DivisionByZero ) ,
276- RemainderByZero => err_panic ! ( RemainderByZero ) ,
277- ResumedAfterReturn ( generator_kind) => err_panic ! ( ResumedAfterReturn ( * generator_kind) ) ,
278- ResumedAfterPanic ( generator_kind) => err_panic ! ( ResumedAfterPanic ( * generator_kind) ) ,
301+ Overflow ( op) => Overflow ( * op) ,
302+ OverflowNeg => OverflowNeg ,
303+ DivisionByZero => DivisionByZero ,
304+ RemainderByZero => RemainderByZero ,
305+ ResumedAfterReturn ( generator_kind) => ResumedAfterReturn ( * generator_kind) ,
306+ ResumedAfterPanic ( generator_kind) => ResumedAfterPanic ( * generator_kind) ,
279307 Panic { .. } => bug ! ( "`Panic` variant cannot occur in MIR" ) ,
280- }
281- . into ( ) )
308+ } ;
309+ Err ( ConstEvalErrKind :: Panic ( err ) . into ( ) )
282310 }
283311
284312 fn ptr_to_int ( _mem : & Memory < ' mir , ' tcx , Self > , _ptr : Pointer ) -> InterpResult < ' tcx , u64 > {
285- Err ( ConstEvalError :: NeedsRfc ( "pointer-to-integer cast" . to_string ( ) ) . into ( ) )
313+ Err ( ConstEvalErrKind :: NeedsRfc ( "pointer-to-integer cast" . to_string ( ) ) . into ( ) )
286314 }
287315
288316 fn binary_ptr_op (
@@ -291,7 +319,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
291319 _left : ImmTy < ' tcx > ,
292320 _right : ImmTy < ' tcx > ,
293321 ) -> InterpResult < ' tcx , ( Scalar , bool , Ty < ' tcx > ) > {
294- Err ( ConstEvalError :: NeedsRfc ( "pointer arithmetic or comparison" . to_string ( ) ) . into ( ) )
322+ Err ( ConstEvalErrKind :: NeedsRfc ( "pointer arithmetic or comparison" . to_string ( ) ) . into ( ) )
295323 }
296324
297325 fn find_foreign_static (
@@ -321,7 +349,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
321349 _ecx : & mut InterpCx < ' mir , ' tcx , Self > ,
322350 _dest : PlaceTy < ' tcx > ,
323351 ) -> InterpResult < ' tcx > {
324- Err ( ConstEvalError :: NeedsRfc ( "heap allocations via `box` keyword" . to_string ( ) ) . into ( ) )
352+ Err ( ConstEvalErrKind :: NeedsRfc ( "heap allocations via `box` keyword" . to_string ( ) ) . into ( ) )
325353 }
326354
327355 fn before_terminator ( ecx : & mut InterpCx < ' mir , ' tcx , Self > ) -> InterpResult < ' tcx > {
@@ -355,7 +383,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
355383 if memory_extra. can_access_statics {
356384 Ok ( ( ) )
357385 } else {
358- Err ( ConstEvalError :: ConstAccessesStatic . into ( ) )
386+ Err ( ConstEvalErrKind :: ConstAccessesStatic . into ( ) )
359387 }
360388 }
361389}
0 commit comments