Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 59 additions & 12 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,40 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
if let Some((value, _ty)) = tcx.trivial_const(key.value.instance.def_id()) {
let ty::PseudoCanonicalInput { typing_env, value } = key;

if let Some((value, _ty)) = tcx.trivial_const(value.instance.def_id()) {
return Ok(value);
}

match typing_env.typing_mode().assert_not_erased() {
ty::TypingMode::PostAnalysis => {}
// We are in codegen. It's very likely this constant has been evaluated in PostAnalysis before.
// Try to reuse this evaluation, and only re-run if we hit a `TooGeneric` error.
ty::TypingMode::Codegen => {
let with_postanalysis =
ty::TypingEnv::new(typing_env.param_env, ty::TypingMode::PostAnalysis);
let with_postanalysis =
tcx.eval_to_const_value_raw(with_postanalysis.as_query_input(value));
match with_postanalysis {
Ok(_) | Err(ErrorHandled::Reported(..)) => return with_postanalysis,
Err(ErrorHandled::TooGeneric(_)) => {}
}
}
// Const eval always happens in PostAnalysis or Codegen mode. See the comment in
// `InterpCx::new` for more details.
ty::TypingMode::Coherence
| ty::TypingMode::Analysis { .. }
| ty::TypingMode::Borrowck { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. } => {
if cfg!(debug_assertions) {
bug!(
"Const eval should always happens in PostAnalysis or Codegen mode. See the comment in `InterpCx::new` for more details."
)
}
}
}

tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
}

Expand Down Expand Up @@ -369,33 +400,49 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
let ty::PseudoCanonicalInput { typing_env, value } = key;

// This shouldn't be used for statics, since statics are conceptually places,
// not values -- so what we do here could break pointer identity.
assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id()));

if cfg!(debug_assertions) {
match key.typing_env.typing_mode().assert_not_erased() {
ty::TypingMode::PostAnalysis => {}
ty::TypingMode::Coherence
| ty::TypingMode::Analysis { .. }
| ty::TypingMode::Borrowck { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. } => {
match key.typing_env.typing_mode().assert_not_erased() {
ty::TypingMode::PostAnalysis => {}
// We are in codegen. It's very likely this constant has been evaluated in PostAnalysis before.
// Try to reuse this evaluation, and only re-run if we hit a `TooGeneric` error.
ty::TypingMode::Codegen => {
let with_postanalysis =
ty::TypingEnv::new(typing_env.param_env, ty::TypingMode::PostAnalysis);
let with_postanalysis =
tcx.eval_to_allocation_raw(with_postanalysis.as_query_input(value));
match with_postanalysis {
Ok(_) | Err(ErrorHandled::Reported(..)) => return with_postanalysis,
Err(ErrorHandled::TooGeneric(_)) => {}
}
}
ty::TypingMode::Coherence
| ty::TypingMode::Analysis { .. }
| ty::TypingMode::Borrowck { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. } => {
if cfg!(debug_assertions) {
bug!(
"Const eval should always happens in PostAnalysis mode. See the comment in `InterpCx::new` for more details."
"Const eval should always happens in PostAnalysis or Codegen mode. See the comment in `InterpCx::new` for more details."
)
}
}
}

if cfg!(debug_assertions) {
// Make sure we format the instance even if we do not print it.
// This serves as a regression test against an ICE on printing.
// The next two lines concatenated contain some discussion:
// https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/
// subject/anon_const_instance_printing/near/135980032
let instance = with_no_trimmed_paths!(key.value.instance.to_string());
trace!("const eval: {:?} ({})", key, instance);
let instance = with_no_trimmed_paths!(value.instance.to_string());
trace!("const eval: {:?} ({}) inside {:?}", value, instance, typing_env);
}

eval_in_interpreter(tcx, key.value, key.typing_env)
eval_in_interpreter(tcx, value, typing_env)
}

fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,13 @@ pub(crate) fn eval_to_valtree<'tcx>(
) -> EvalToValTreeResult<'tcx> {
if cfg!(debug_assertions) {
match typing_env.typing_mode().assert_not_erased() {
ty::TypingMode::PostAnalysis => {}
ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen => {}
ty::TypingMode::Coherence
| ty::TypingMode::Analysis { .. }
| ty::TypingMode::Borrowck { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. } => {
bug!(
"Const eval should always happens in PostAnalysis mode. See the comment in `InterpCx::new` for more details."
"Const eval should always happens in PostAnalysis or Codegen mode. See the comment in `InterpCx::new` for more details."
)
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// already been revealed, so we'd be able to at least partially observe the hidden types anyways.
if cfg!(debug_assertions) {
match typing_env.typing_mode().assert_not_erased() {
TypingMode::PostAnalysis => {}
TypingMode::PostAnalysis | TypingMode::Codegen => {}
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } => {
bug!("Const eval should always happens in PostAnalysis mode.");
bug!("Const eval should always happens in PostAnalysis or Codegen mode.");
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::TypingMode::Coherence
| ty::TypingMode::Borrowck { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. }
| ty::TypingMode::PostAnalysis => {
| ty::TypingMode::PostAnalysis
| ty::TypingMode::Codegen => {
bug!()
}
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub(crate) fn check_transmutes(tcx: TyCtxt<'_>, owner: LocalDefId) {
let typeck_results = tcx.typeck(owner);
let None = typeck_results.tainted_by_errors else { return };

let typing_env = ty::TypingEnv::post_analysis(tcx, owner);
let typing_env = ty::TypingEnv::codegen(tcx, owner);
for &(from, to, hir_id) in &typeck_results.transmutes_to_check {
check_transmute(tcx, typing_env, from, to, hir_id);
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
ty::TypingMode::Coherence
| ty::TypingMode::Borrowck { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. }
| ty::TypingMode::PostAnalysis => {
| ty::TypingMode::PostAnalysis
| ty::TypingMode::Codegen => {
bug!()
}
};
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ impl<'tcx> Drop for InferCtxt<'tcx> {
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => {}
| TypingMode::PostAnalysis
| TypingMode::Codegen => {}
// In erased mode, the opaque type storage is always empty
TypingMode::ErasedNotCoherence(..) => {}
TypingMode::Borrowck { .. } => {
Expand Down Expand Up @@ -1156,7 +1157,8 @@ impl<'tcx> InferCtxt<'tcx> {
// to support PostBorrowckAnalysis in the old solver as well.
TypingMode::Coherence
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => false,
| TypingMode::PostAnalysis
| TypingMode::Codegen => false,
}
}

Expand Down Expand Up @@ -1486,7 +1488,8 @@ impl<'tcx> InferCtxt<'tcx> {
}
mode @ (ty::TypingMode::Coherence
| ty::TypingMode::PostBorrowckAnalysis { .. }
| ty::TypingMode::PostAnalysis) => mode,
| ty::TypingMode::PostAnalysis
| ty::TypingMode::Codegen) => mode,
ty::TypingMode::ErasedNotCoherence(MayBeErased) => unreachable!(),
};
ty::TypingEnv::new(param_env, typing_mode)
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_infer/src/infer/opaque_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,9 @@ impl<'tcx> InferCtxt<'tcx> {
.map(|obligation| obligation.as_goal()),
);
}
mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => {
mode @ (ty::TypingMode::PostBorrowckAnalysis { .. }
| ty::TypingMode::PostAnalysis
| ty::TypingMode::Codegen) => {
bug!("insert hidden type in {mode:?}")
}
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,10 +1180,10 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
&& (!tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()))
{
// Eagerly check the unsubstituted layout for cycles.
tcx.ensure_ok().layout_of(
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
.as_query_input(tcx.type_of(def_id).instantiate_identity().skip_norm_wip()),
);
tcx.ensure_ok()
.layout_of(ty::TypingEnv::codegen(tcx, def_id.to_def_id()).as_query_input(
tcx.type_of(def_id).instantiate_identity().skip_norm_wip(),
));
}
});
});
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1649,7 +1649,7 @@ rustc_queries! {
/// Like `param_env`, but returns the `ParamEnv` after all opaque types have been
/// replaced with their hidden type. This is used in the old trait solver
/// when in `PostAnalysis` mode and should not be called directly.
query typing_env_normalized_for_post_analysis(def_id: DefId) -> ty::TypingEnv<'tcx> {
query param_env_normalized_for_post_analysis(def_id: DefId) -> ty::ParamEnv<'tcx> {
desc { "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) }
}

Expand Down
64 changes: 44 additions & 20 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,17 @@ impl<'tcx> ParamEnv<'tcx> {
pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
ParamEnvAnd { param_env: self, value }
}

/// Eagerly reveal all opaque types in the `param_env`.
pub fn with_normalized(self, tcx: TyCtxt<'tcx>) -> ParamEnv<'tcx> {
// No need to reveal opaques with the new solver enabled,
// since we have lazy norm.
if tcx.next_trait_solver_globally() {
self
} else {
ParamEnv::new(tcx.reveal_opaque_types_in_bounds(self.caller_bounds))
}
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
Expand Down Expand Up @@ -1071,7 +1082,7 @@ impl<'tcx> TypingEnv<'tcx> {
/// use `TypingMode::PostAnalysis`, they may still have where-clauses
/// in scope.
pub fn fully_monomorphized() -> TypingEnv<'tcx> {
Self::new(ParamEnv::empty(), TypingMode::PostAnalysis)
Self::new(ParamEnv::empty(), TypingMode::Codegen)
}

/// Create a typing environment for use during analysis outside of a body.
Expand All @@ -1088,31 +1099,44 @@ impl<'tcx> TypingEnv<'tcx> {
}

pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey<DefId>) -> TypingEnv<'tcx> {
let def_id = def_id.into_query_key();
tcx.typing_env_normalized_for_post_analysis(def_id)
TypingEnv::new(tcx.param_env_normalized_for_post_analysis(def_id), TypingMode::PostAnalysis)
}

/// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all
/// opaque types in the `param_env`.
pub fn codegen(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey<DefId>) -> TypingEnv<'tcx> {
TypingEnv::new(tcx.param_env_normalized_for_post_analysis(def_id), TypingMode::Codegen)
}

/// Modify the `typing_mode` to `PostAnalysis` or `Codegen` and eagerly reveal all opaque types
/// in the `param_env`.
pub fn with_post_analysis_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
let TypingEnv { typing_mode, param_env } = self;
match typing_mode.0.assert_not_erased() {
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } => {}
TypingMode::PostAnalysis | TypingMode::Codegen => return self,
}

// No need to reveal opaques with the new solver enabled,
// since we have lazy norm.
let param_env = if tcx.next_trait_solver_globally() {
param_env
} else {
match typing_mode.0.assert_not_erased() {
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } => {}
TypingMode::PostAnalysis => return self,
}
let param_env = param_env.with_normalized(tcx);
TypingEnv::new(param_env, TypingMode::PostAnalysis)
}

ParamEnv::new(tcx.reveal_opaque_types_in_bounds(param_env.caller_bounds()))
};
TypingEnv { typing_mode: TypingModeEqWrapper(TypingMode::PostAnalysis), param_env }
/// Modify the `typing_mode` to `PostAnalysis` or `Codegen` and eagerly reveal all opaque types
/// in the `param_env`.
pub fn with_codegen_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
let TypingEnv { typing_mode, param_env } = self;
match typing_mode.0.assert_not_erased() {
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => {}
TypingMode::Codegen => return self,
}

let param_env = param_env.with_normalized(tcx);
TypingEnv::new(param_env, TypingMode::Codegen)
}

/// Combine this typing environment with the given `value` to be used by
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,8 @@ impl<'tcx> ConstToPat<'tcx> {
//
// FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself
// instead of having this logic here
let typing_env = self
.tcx
.erase_and_anonymize_regions(self.typing_env)
.with_post_analysis_normalized(self.tcx);
let typing_env =
self.tcx.erase_and_anonymize_regions(self.typing_env).with_codegen_normalized(self.tcx);
let uv = self.tcx.erase_and_anonymize_regions(uv);

// try to resolve e.g. associated constants to their definition on an impl, and then
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/elaborate_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ where
let tcx = self.tcx();

match self.elaborator.typing_env().typing_mode().assert_not_erased() {
ty::TypingMode::PostAnalysis => {}
ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen => {}
ty::TypingMode::Coherence
| ty::TypingMode::Analysis { .. }
| ty::TypingMode::Borrowck { .. }
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ where
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis
| TypingMode::Codegen
| TypingMode::ErasedNotCoherence(MayBeErased) => !candidates.iter().any(|c| {
matches!(
c.source,
Expand Down Expand Up @@ -1056,7 +1057,8 @@ where
TypingMode::Coherence
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => vec![],
| TypingMode::PostAnalysis
| TypingMode::Codegen => vec![],
TypingMode::ErasedNotCoherence(MayBeErased) => {
self.opaque_accesses
.rerun_if_any_opaque_has_infer_as_hidden_type(RerunReason::SelfTyInfer)?;
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,10 @@ where
// =============================
(RerunCondition::Always, _) => RerunDecision::Yes,
// =============================
(RerunCondition::OpaqueInStorage(..), TypingMode::PostAnalysis) => RerunDecision::Yes,
(
RerunCondition::OpaqueInStorage(..),
TypingMode::PostAnalysis | TypingMode::Codegen,
) => RerunDecision::Yes,
(
RerunCondition::OpaqueInStorage(defids),
TypingMode::PostBorrowckAnalysis { defined_opaque_types: opaques }
Expand All @@ -786,12 +789,13 @@ where
RerunCondition::AnyOpaqueHasInferAsHidden,
TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis
| TypingMode::Codegen
| TypingMode::Borrowck { .. },
) => RerunDecision::No,
// =============================
(
RerunCondition::OpaqueInStorageOrAnyOpaqueHasInferAsHidden(_),
TypingMode::PostAnalysis,
TypingMode::PostAnalysis | TypingMode::Codegen,
) => RerunDecision::No,
(
RerunCondition::OpaqueInStorageOrAnyOpaqueHasInferAsHidden(defids),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_next_trait_solver/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ where
.assert_not_erased()
{
// Opaques are never rigid outside of analysis mode.
TypingMode::Coherence | TypingMode::PostAnalysis => false,
TypingMode::Coherence | TypingMode::PostAnalysis | TypingMode::Codegen => false,
// During analysis, opaques are rigid unless they may be defined by
// the current body.
TypingMode::Analysis { defining_opaque_types_and_generators: non_rigid_opaques }
Expand Down
Loading
Loading