@@ -28,13 +28,6 @@ use super::eval_context::{LocalValue, StackPopCleanup};
2828use super :: { Frame , Memory , Operand , MemPlace , Place , Value } ;
2929use const_eval:: CompileTimeInterpreter ;
3030
31- /// Number of steps until the detector even starts doing anything.
32- /// Also, a warning is shown to the user when this number is reached.
33- pub ( crate ) const STEPS_UNTIL_DETECTOR_ENABLED : isize = 1_000_000 ;
34- /// The number of steps between loop detector snapshots.
35- /// Should be a power of two for performance reasons.
36- pub ( crate ) const DETECTOR_SNAPSHOT_PERIOD : isize = 256 ;
37-
3831#[ derive( Default ) ]
3932pub ( crate ) struct InfiniteLoopDetector < ' a , ' mir , ' tcx : ' a + ' mir > {
4033 /// The set of all `EvalSnapshot` *hashes* observed by this detector.
@@ -53,28 +46,31 @@ pub(crate) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir> {
5346
5447impl < ' a , ' mir , ' tcx > InfiniteLoopDetector < ' a , ' mir , ' tcx >
5548{
56- /// Returns `true` if the loop detector has not yet observed a snapshot.
57- pub fn is_empty ( & self ) -> bool {
58- self . hashes . is_empty ( )
59- }
60-
6149 pub fn observe_and_analyze < ' b > (
6250 & mut self ,
6351 tcx : & TyCtxt < ' b , ' tcx , ' tcx > ,
52+ span : Span ,
6453 memory : & Memory < ' a , ' mir , ' tcx , CompileTimeInterpreter < ' a , ' mir , ' tcx > > ,
6554 stack : & [ Frame < ' mir , ' tcx > ] ,
6655 ) -> EvalResult < ' tcx , ( ) > {
67-
56+ // Compute stack's hash before copying anything
6857 let mut hcx = tcx. get_stable_hashing_context ( ) ;
6958 let mut hasher = StableHasher :: < u64 > :: new ( ) ;
7059 stack. hash_stable ( & mut hcx, & mut hasher) ;
7160 let hash = hasher. finish ( ) ;
7261
62+ // Check if we know that hash already
63+ if self . hashes . is_empty ( ) {
64+ // FIXME(#49980): make this warning a lint
65+ tcx. sess . span_warn ( span,
66+ "Constant evaluating a complex constant, this might take some time" ) ;
67+ }
7368 if self . hashes . insert ( hash) {
7469 // No collision
7570 return Ok ( ( ) )
7671 }
7772
73+ // We need to make a full copy. NOW things that to get really expensive.
7874 info ! ( "snapshotting the state of the interpreter" ) ;
7975
8076 if self . snapshots . insert ( EvalSnapshot :: new ( memory, stack) ) {
@@ -461,6 +457,9 @@ impl<'a, 'mir, 'tcx> Eq for EvalSnapshot<'a, 'mir, 'tcx>
461457impl < ' a , ' mir , ' tcx > PartialEq for EvalSnapshot < ' a , ' mir , ' tcx >
462458{
463459 fn eq ( & self , other : & Self ) -> bool {
460+ // FIXME: This looks to be a *ridicolously expensive* comparison operation.
461+ // Doesn't this make tons of copies? Either `snapshot` is very badly named,
462+ // or it does!
464463 self . snapshot ( ) == other. snapshot ( )
465464 }
466465}
0 commit comments