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