Skip to content

Commit ac71b54

Browse files
committed
Reduce TypingMode duplication.
1 parent 4b6f78d commit ac71b54

4 files changed

Lines changed: 68 additions & 91 deletions

File tree

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::mir::{self, ConstAlloc, ConstValue};
88
use rustc_middle::query::TyCtxtAt;
99
use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout};
1010
use 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};
1212
use rustc_middle::{bug, throw_inval};
1313
use rustc_span::Span;
1414
use rustc_span::def_id::LocalDefId;
@@ -23,6 +23,33 @@ use crate::interpret::{
2323
};
2424
use 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+
2653
fn 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

448432
fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(

compiler/rustc_const_eval/src/const_eval/valtrees.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -241,19 +241,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
241241
typing_env: ty::TypingEnv<'tcx>,
242242
cid: GlobalId<'tcx>,
243243
) -> EvalToValTreeResult<'tcx> {
244-
if cfg!(debug_assertions) {
245-
match typing_env.typing_mode().assert_not_erased() {
246-
ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen => {}
247-
ty::TypingMode::Coherence
248-
| ty::TypingMode::Analysis { .. }
249-
| ty::TypingMode::Borrowck { .. }
250-
| ty::TypingMode::PostBorrowckAnalysis { .. } => {
251-
bug!(
252-
"Const eval should always happens in PostAnalysis or Codegen mode. See the comment in `InterpCx::new` for more details."
253-
)
254-
}
255-
}
256-
}
244+
crate::assert_typing_mode(typing_env.typing_mode());
257245
let const_alloc = tcx.eval_to_allocation_raw(typing_env.as_query_input(cid))?;
258246

259247
// FIXME Need to provide a span to `eval_to_valtree`

compiler/rustc_const_eval/src/interpret/eval_context.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ use rustc_middle::ty::layout::{
99
LayoutOfHelpers, TyAndLayout,
1010
};
1111
use rustc_middle::ty::{
12-
self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingEnv, TypingMode,
13-
Variance,
12+
self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingEnv, Variance,
1413
};
15-
use rustc_middle::{bug, mir, span_bug};
14+
use rustc_middle::{mir, span_bug};
1615
use rustc_span::Span;
1716
use rustc_target::callconv::FnAbi;
1817
use tracing::{debug, trace};
@@ -238,21 +237,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
238237
typing_env: ty::TypingEnv<'tcx>,
239238
machine: M,
240239
) -> Self {
241-
// Const eval always happens in post analysis mode in order to be able to use the hidden types of
242-
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
243-
// types that are not specified in the opaque type. We also use MIR bodies whose opaque types have
244-
// already been revealed, so we'd be able to at least partially observe the hidden types anyways.
245-
if cfg!(debug_assertions) {
246-
match typing_env.typing_mode().assert_not_erased() {
247-
TypingMode::PostAnalysis | TypingMode::Codegen => {}
248-
TypingMode::Coherence
249-
| TypingMode::Analysis { .. }
250-
| TypingMode::Borrowck { .. }
251-
| TypingMode::PostBorrowckAnalysis { .. } => {
252-
bug!("Const eval should always happens in PostAnalysis or Codegen mode.");
253-
}
254-
}
255-
}
240+
crate::assert_typing_mode(typing_env.typing_mode());
256241

257242
InterpCx {
258243
machine,

compiler/rustc_const_eval/src/lib.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,28 @@ pub mod util;
1818

1919
use std::sync::atomic::AtomicBool;
2020

21-
use rustc_middle::ty;
2221
use rustc_middle::util::Providers;
22+
use rustc_middle::{bug, ty};
23+
24+
/// Const eval always happens in post analysis mode in order to be able to use the hidden types of
25+
/// opaque types. This is needed for trivial things like `size_of`, but also for using associated
26+
/// types that are not specified in the opaque type. We also use MIR bodies whose opaque types have
27+
/// already been revealed, so we'd be able to at least partially observe the hidden types anyways.
28+
fn assert_typing_mode(typing_mode: ty::TypingMode<'_>) {
29+
if cfg!(debug_assertions) {
30+
match typing_mode.assert_not_erased() {
31+
ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen => {}
32+
// Const eval always happens in PostAnalysis or Codegen mode. See the comment in
33+
// `InterpCx::new` for more details.
34+
ty::TypingMode::Coherence
35+
| ty::TypingMode::Analysis { .. }
36+
| ty::TypingMode::Borrowck { .. }
37+
| ty::TypingMode::PostBorrowckAnalysis { .. } => bug!(
38+
"Const eval should always happens in PostAnalysis or Codegen mode. See the comment on `assert_typing_mode` for more details."
39+
),
40+
}
41+
}
42+
}
2343

2444
pub fn provide(providers: &mut Providers) {
2545
const_eval::provide(&mut providers.queries);

0 commit comments

Comments
 (0)