|
| 1 | +use std::assert_matches::debug_assert_matches; |
1 | 2 | use std::sync::atomic::Ordering::Relaxed; |
2 | 3 |
|
3 | 4 | use either::{Left, Right}; |
@@ -292,6 +293,30 @@ pub fn eval_to_const_value_raw_provider<'tcx>( |
292 | 293 | tcx: TyCtxt<'tcx>, |
293 | 294 | key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>, |
294 | 295 | ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { |
| 296 | + let ty::PseudoCanonicalInput { typing_env, value } = key; |
| 297 | + |
| 298 | + // Const eval always happens in PostAnalysis or Codegen mode. See the comment in |
| 299 | + // `InterpCx::new` for more details. |
| 300 | + debug_assert_matches!( |
| 301 | + typing_env.typing_mode, |
| 302 | + ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen |
| 303 | + ); |
| 304 | + |
| 305 | + // We are in codegen. It's very likely this constant has been evaluated in PostAnalysis before. |
| 306 | + // Try to reuse this evaluation, and only re-run if we hit a `TooGeneric` error. |
| 307 | + if let ty::TypingMode::Codegen = typing_env.typing_mode { |
| 308 | + let with_postanalysis = ty::TypingEnv { |
| 309 | + typing_mode: ty::TypingMode::PostAnalysis, |
| 310 | + param_env: typing_env.param_env, |
| 311 | + }; |
| 312 | + let with_postanalysis = |
| 313 | + tcx.eval_to_const_value_raw(with_postanalysis.as_query_input(value)); |
| 314 | + match with_postanalysis { |
| 315 | + Ok(_) | Err(ErrorHandled::Reported(..)) => return with_postanalysis, |
| 316 | + Err(ErrorHandled::TooGeneric(_)) => {} |
| 317 | + } |
| 318 | + } |
| 319 | + |
295 | 320 | tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key)) |
296 | 321 | } |
297 | 322 |
|
@@ -331,23 +356,44 @@ pub fn eval_to_allocation_raw_provider<'tcx>( |
331 | 356 | tcx: TyCtxt<'tcx>, |
332 | 357 | key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>, |
333 | 358 | ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { |
| 359 | + let ty::PseudoCanonicalInput { typing_env, value } = key; |
| 360 | + |
334 | 361 | // This shouldn't be used for statics, since statics are conceptually places, |
335 | 362 | // 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 |
| 363 | + assert!(value.promoted.is_some() || !tcx.is_static(value.instance.def_id())); |
| 364 | + |
| 365 | + // Const eval always happens in PostAnalysis or Codegen mode. See the comment in |
338 | 366 | // `InterpCx::new` for more details. |
339 | | - debug_assert_eq!(key.typing_env.typing_mode, ty::TypingMode::PostAnalysis); |
| 367 | + debug_assert_matches!( |
| 368 | + typing_env.typing_mode, |
| 369 | + ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen |
| 370 | + ); |
| 371 | + |
340 | 372 | if cfg!(debug_assertions) { |
341 | 373 | // Make sure we format the instance even if we do not print it. |
342 | 374 | // This serves as a regression test against an ICE on printing. |
343 | 375 | // The next two lines concatenated contain some discussion: |
344 | 376 | // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/ |
345 | 377 | // 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); |
| 378 | + let instance = with_no_trimmed_paths!(value.instance.to_string()); |
| 379 | + trace!("const eval: {:?} ({}) inside {:?}", value, instance, typing_env); |
| 380 | + } |
| 381 | + |
| 382 | + // We are in codegen. It's very likely this constant has been evaluated in PostAnalysis before. |
| 383 | + // Try to reuse this evaluation, and only re-run if we hit a `TooGeneric` error. |
| 384 | + if let ty::TypingMode::Codegen = typing_env.typing_mode { |
| 385 | + let with_postanalysis = ty::TypingEnv { |
| 386 | + typing_mode: ty::TypingMode::PostAnalysis, |
| 387 | + param_env: typing_env.param_env, |
| 388 | + }; |
| 389 | + let with_postanalysis = tcx.eval_to_allocation_raw(with_postanalysis.as_query_input(value)); |
| 390 | + match with_postanalysis { |
| 391 | + Ok(_) | Err(ErrorHandled::Reported(..)) => return with_postanalysis, |
| 392 | + Err(ErrorHandled::TooGeneric(_)) => {} |
| 393 | + } |
348 | 394 | } |
349 | 395 |
|
350 | | - eval_in_interpreter(tcx, key.value, key.typing_env) |
| 396 | + eval_in_interpreter(tcx, value, typing_env) |
351 | 397 | } |
352 | 398 |
|
353 | 399 | fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( |
|
0 commit comments