@@ -8,7 +8,7 @@ use rustc_middle::mir::{self, ConstAlloc, ConstValue};
88use rustc_middle:: query:: TyCtxtAt ;
99use rustc_middle:: ty:: layout:: { HasTypingEnv , TyAndLayout } ;
1010use rustc_middle:: ty:: print:: with_no_trimmed_paths;
11- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
11+ use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeVisitable } ;
1212use rustc_middle:: { bug, throw_inval} ;
1313use rustc_span:: Span ;
1414use rustc_span:: def_id:: LocalDefId ;
@@ -23,6 +23,33 @@ use crate::interpret::{
2323} ;
2424use crate :: { CTRL_C_RECEIVED , errors} ;
2525
26+ fn retry_codegen_mode_with_postanalysis < ' tcx , K : TypeVisitable < TyCtxt < ' tcx > > , V > (
27+ key : ty:: PseudoCanonicalInput < ' tcx , K > ,
28+ f : impl FnOnce ( ty:: PseudoCanonicalInput < ' tcx , K > ) -> Result < V , ErrorHandled > ,
29+ ) -> Option < Result < V , ErrorHandled > > {
30+ let ty:: PseudoCanonicalInput { typing_env, value } = key;
31+ match typing_env. typing_mode ( ) . assert_not_erased ( ) {
32+ // We are in codegen. It's very likely this constant has been evaluated in PostAnalysis
33+ // before. Try to reuse this evaluation, and only re-run if we hit a `TooGeneric` error.
34+ ty:: TypingMode :: Codegen => {
35+ let with_postanalysis =
36+ ty:: TypingEnv :: new ( typing_env. param_env , ty:: TypingMode :: PostAnalysis ) ;
37+ let with_postanalysis = f ( with_postanalysis. as_query_input ( value) ) ;
38+ match with_postanalysis {
39+ Ok ( _) | Err ( ErrorHandled :: Reported ( ..) ) => return Some ( with_postanalysis) ,
40+ Err ( ErrorHandled :: TooGeneric ( _) ) => { }
41+ }
42+ }
43+ ty:: TypingMode :: Coherence
44+ | ty:: TypingMode :: Analysis { .. }
45+ | ty:: TypingMode :: Borrowck { .. }
46+ | ty:: TypingMode :: PostBorrowckAnalysis { .. }
47+ | ty:: TypingMode :: PostAnalysis => { }
48+ }
49+
50+ None
51+ }
52+
2653fn setup_for_eval < ' tcx > (
2754 ecx : & mut CompileTimeInterpCx < ' tcx > ,
2855 cid : GlobalId < ' tcx > ,
@@ -327,38 +354,16 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
327354 tcx : TyCtxt < ' tcx > ,
328355 key : ty:: PseudoCanonicalInput < ' tcx , GlobalId < ' tcx > > ,
329356) -> :: rustc_middle:: mir:: interpret:: EvalToConstValueResult < ' tcx > {
330- let ty :: PseudoCanonicalInput { typing_env , value } = key;
357+ crate :: assert_typing_mode ( key. typing_env . typing_mode ( ) ) ;
331358
332- if let Some ( ( value, _ty) ) = tcx. trivial_const ( value. instance . def_id ( ) ) {
359+ if let Some ( ( value, _ty) ) = tcx. trivial_const ( key . value . instance . def_id ( ) ) {
333360 return Ok ( value) ;
334361 }
335362
336- match typing_env. typing_mode ( ) . assert_not_erased ( ) {
337- ty:: TypingMode :: PostAnalysis => { }
338- // We are in codegen. It's very likely this constant has been evaluated in PostAnalysis before.
339- // Try to reuse this evaluation, and only re-run if we hit a `TooGeneric` error.
340- ty:: TypingMode :: Codegen => {
341- let with_postanalysis =
342- ty:: TypingEnv :: new ( typing_env. param_env , ty:: TypingMode :: PostAnalysis ) ;
343- let with_postanalysis =
344- tcx. eval_to_const_value_raw ( with_postanalysis. as_query_input ( value) ) ;
345- match with_postanalysis {
346- Ok ( _) | Err ( ErrorHandled :: Reported ( ..) ) => return with_postanalysis,
347- Err ( ErrorHandled :: TooGeneric ( _) ) => { }
348- }
349- }
350- // Const eval always happens in PostAnalysis or Codegen mode. See the comment in
351- // `InterpCx::new` for more details.
352- ty:: TypingMode :: Coherence
353- | ty:: TypingMode :: Analysis { .. }
354- | ty:: TypingMode :: Borrowck { .. }
355- | ty:: TypingMode :: PostBorrowckAnalysis { .. } => {
356- if cfg ! ( debug_assertions) {
357- bug ! (
358- "Const eval should always happens in PostAnalysis or Codegen mode. See the comment in `InterpCx::new` for more details."
359- )
360- }
361- }
363+ if let Some ( retry) =
364+ retry_codegen_mode_with_postanalysis ( key, |key| tcx. eval_to_const_value_raw ( key) )
365+ {
366+ return retry;
362367 }
363368
364369 tcx. eval_to_allocation_raw ( key) . map ( |val| turn_into_const_value ( tcx, val, key) )
@@ -400,49 +405,28 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
400405 tcx : TyCtxt < ' tcx > ,
401406 key : ty:: PseudoCanonicalInput < ' tcx , GlobalId < ' tcx > > ,
402407) -> :: rustc_middle:: mir:: interpret:: EvalToAllocationRawResult < ' tcx > {
403- let ty:: PseudoCanonicalInput { typing_env, value } = key;
408+ crate :: assert_typing_mode ( key. typing_env . typing_mode ( ) ) ;
409+ if let Some ( retry) =
410+ retry_codegen_mode_with_postanalysis ( key, |key| tcx. eval_to_allocation_raw ( key) )
411+ {
412+ return retry;
413+ }
404414
405415 // This shouldn't be used for statics, since statics are conceptually places,
406416 // not values -- so what we do here could break pointer identity.
407417 assert ! ( key. value. promoted. is_some( ) || !tcx. is_static( key. value. instance. def_id( ) ) ) ;
408418
409- match key. typing_env . typing_mode ( ) . assert_not_erased ( ) {
410- ty:: TypingMode :: PostAnalysis => { }
411- // We are in codegen. It's very likely this constant has been evaluated in PostAnalysis before.
412- // Try to reuse this evaluation, and only re-run if we hit a `TooGeneric` error.
413- ty:: TypingMode :: Codegen => {
414- let with_postanalysis =
415- ty:: TypingEnv :: new ( typing_env. param_env , ty:: TypingMode :: PostAnalysis ) ;
416- let with_postanalysis =
417- tcx. eval_to_allocation_raw ( with_postanalysis. as_query_input ( value) ) ;
418- match with_postanalysis {
419- Ok ( _) | Err ( ErrorHandled :: Reported ( ..) ) => return with_postanalysis,
420- Err ( ErrorHandled :: TooGeneric ( _) ) => { }
421- }
422- }
423- ty:: TypingMode :: Coherence
424- | ty:: TypingMode :: Analysis { .. }
425- | ty:: TypingMode :: Borrowck { .. }
426- | ty:: TypingMode :: PostBorrowckAnalysis { .. } => {
427- if cfg ! ( debug_assertions) {
428- bug ! (
429- "Const eval should always happens in PostAnalysis or Codegen mode. See the comment in `InterpCx::new` for more details."
430- )
431- }
432- }
433- }
434-
435419 if cfg ! ( debug_assertions) {
436420 // Make sure we format the instance even if we do not print it.
437421 // This serves as a regression test against an ICE on printing.
438422 // The next two lines concatenated contain some discussion:
439423 // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/
440424 // subject/anon_const_instance_printing/near/135980032
441- let instance = with_no_trimmed_paths ! ( value. instance. to_string( ) ) ;
442- trace ! ( "const eval: {:?} ({}) inside {:?} " , value , instance, typing_env ) ;
425+ let instance = with_no_trimmed_paths ! ( key . value. instance. to_string( ) ) ;
426+ trace ! ( "const eval: {:?} ({})" , key , instance) ;
443427 }
444428
445- eval_in_interpreter ( tcx, value, typing_env)
429+ eval_in_interpreter ( tcx, key . value , key . typing_env )
446430}
447431
448432fn eval_in_interpreter < ' tcx , R : InterpretationResult < ' tcx > > (
0 commit comments