|
| 1 | +use std::assert_matches::debug_assert_matches; |
1 | 2 | use std::sync::atomic::Ordering::Relaxed;
|
2 | 3 |
|
3 | 4 | use either::{Left, Right};
|
@@ -331,23 +332,44 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
|
331 | 332 | tcx: TyCtxt<'tcx>,
|
332 | 333 | key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
|
333 | 334 | ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
|
| 335 | + let ty::PseudoCanonicalInput { typing_env, value } = key; |
| 336 | + |
334 | 337 | // This shouldn't be used for statics, since statics are conceptually places,
|
335 | 338 | // not values -- so what we do here could break pointer identity.
|
336 |
| - assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id())); |
337 |
| - // Const eval always happens in PostAnalysis mode . See the comment in |
| 339 | + assert!(value.promoted.is_some() || !tcx.is_static(value.instance.def_id())); |
| 340 | + |
| 341 | + // Const eval always happens in PostAnalysis or Codegen mode. See the comment in |
338 | 342 | // `InterpCx::new` for more details.
|
339 |
| - debug_assert_eq!(key.typing_env.typing_mode, ty::TypingMode::PostAnalysis); |
| 343 | + debug_assert_matches!( |
| 344 | + typing_env.typing_mode, |
| 345 | + ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen |
| 346 | + ); |
| 347 | + |
340 | 348 | if cfg!(debug_assertions) {
|
341 | 349 | // Make sure we format the instance even if we do not print it.
|
342 | 350 | // This serves as a regression test against an ICE on printing.
|
343 | 351 | // The next two lines concatenated contain some discussion:
|
344 | 352 | // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/
|
345 | 353 | // subject/anon_const_instance_printing/near/135980032
|
346 |
| - let instance = with_no_trimmed_paths!(key.value.instance.to_string()); |
347 |
| - trace!("const eval: {:?} ({})", key, instance); |
| 354 | + let instance = with_no_trimmed_paths!(value.instance.to_string()); |
| 355 | + trace!("const eval: {:?} ({}) inside {:?}", value, instance, typing_env); |
| 356 | + } |
| 357 | + |
| 358 | + // We are in codegen. It's very likely this constant has been evaluated in PostAnalysis before. |
| 359 | + // Try to reuse this evaluation, and only re-run if we hit a `TooGeneric` error. |
| 360 | + if let ty::TypingMode::Codegen = typing_env.typing_mode { |
| 361 | + let with_postanalysis = ty::TypingEnv { |
| 362 | + typing_mode: ty::TypingMode::PostAnalysis, |
| 363 | + param_env: typing_env.param_env, |
| 364 | + }; |
| 365 | + let with_postanalysis = tcx.eval_to_allocation_raw(with_postanalysis.as_query_input(value)); |
| 366 | + match with_postanalysis { |
| 367 | + Ok(_) | Err(ErrorHandled::Reported(..)) => return with_postanalysis, |
| 368 | + Err(ErrorHandled::TooGeneric(_)) => {} |
| 369 | + } |
348 | 370 | }
|
349 | 371 |
|
350 |
| - eval_in_interpreter(tcx, key.value, key.typing_env) |
| 372 | + eval_in_interpreter(tcx, value, typing_env) |
351 | 373 | }
|
352 | 374 |
|
353 | 375 | fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
|
|
0 commit comments