type safety for typing mode outside trait solver which can't be erased-not-coherence

This commit is contained in:
Jana Dönszelmann
2026-04-13 13:37:51 +02:00
parent a93f8c0579
commit 630f0d2bbb
33 changed files with 206 additions and 112 deletions
@@ -8,7 +8,7 @@
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, MayBeErased, Ty, TyCtxt};
use rustc_middle::{bug, throw_inval};
use rustc_span::Span;
use rustc_span::def_id::LocalDefId;
@@ -384,7 +384,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
"Const eval should always happens in PostAnalysis mode. See the comment in `InterpCx::new` for more details."
)
}
ty::TypingMode::ErasedNotCoherence => todo!(),
ty::TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
// Make sure we format the instance even if we do not print it.
@@ -3,7 +3,7 @@
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::layout::{LayoutCx, TyAndLayout};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, MayBeErased, Ty, TyCtxt};
use rustc_middle::{bug, mir};
use rustc_span::DUMMY_SP;
use tracing::{debug, instrument, trace};
@@ -247,7 +247,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
"Const eval should always happens in PostAnalysis mode. See the comment in `InterpCx::new` for more details."
)
}
ty::TypingMode::ErasedNotCoherence => todo!(),
ty::TypingMode::ErasedNotCoherence(MayBeErased) => unreachable!(),
}
}
let const_alloc = tcx.eval_to_allocation_raw(typing_env.as_query_input(cid))?;
@@ -9,8 +9,8 @@
LayoutOfHelpers, TyAndLayout,
};
use rustc_middle::ty::{
self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingEnv, TypingMode,
Variance,
self, GenericArgsRef, MayBeErased, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingEnv,
TypingMode, Variance,
};
use rustc_middle::{bug, mir, span_bug};
use rustc_span::Span;
@@ -251,7 +251,7 @@ pub fn new(
| TypingMode::PostBorrowckAnalysis { .. } => {
bug!("Const eval should always happens in PostAnalysis mode.");
}
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => unreachable!(),
}
}
+9 -1
View File
@@ -17,7 +17,9 @@
};
use rustc_infer::infer::{self, RegionVariableOrigin};
use rustc_infer::traits::{DynCompatibilityViolation, Obligation};
use rustc_middle::ty::{self, Const, Flags, Ty, TyCtxt, TypeVisitableExt, Unnormalized};
use rustc_middle::ty::{
self, CantBeErased, Const, Flags, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized,
};
use rustc_session::Session;
use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span};
use rustc_trait_selection::error_reporting::TypeErrCtxt;
@@ -161,6 +163,12 @@ pub(crate) fn new(
}
}
pub(crate) fn typing_mode(&self) -> TypingMode<'tcx, CantBeErased> {
// `FnCtxt` is never constructed in the trait solver, so we can safely use
// `assert_not_erased`.
self.infcx.typing_mode_raw().assert_not_erased()
}
pub(crate) fn dcx(&self) -> DiagCtxtHandle<'a> {
self.root_ctxt.infcx.dcx()
}
@@ -72,7 +72,7 @@ pub fn canonicalize_query<V>(
query_state,
)
.unchecked_map(|(param_env, value)| param_env.and(value));
CanonicalQueryInput { canonical, typing_mode: TypingModeEqWrapper(self.typing_mode()) }
CanonicalQueryInput { canonical, typing_mode: TypingModeEqWrapper(self.typing_mode_raw()) }
}
/// Canonicalizes a query *response* `V`. When we canonicalize a
+2 -2
View File
@@ -26,8 +26,8 @@ fn disable_trait_solver_fast_paths(&self) -> bool {
self.disable_trait_solver_fast_paths()
}
fn typing_mode(&self) -> ty::TypingMode<'tcx> {
self.typing_mode()
fn typing_mode_raw(&self) -> ty::TypingMode<'tcx> {
self.typing_mode_raw()
}
fn universe(&self) -> ty::UniverseIndex {
+29 -8
View File
@@ -34,6 +34,7 @@
TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
};
use rustc_span::{DUMMY_SP, Span, Symbol};
use rustc_type_ir::MayBeErased;
use snapshot::undo_log::InferCtxtUndoLogs;
use tracing::{debug, instrument};
use type_variable::TypeVariableOrigin;
@@ -640,14 +641,34 @@ pub fn next_trait_solver(&self) -> bool {
self.next_trait_solver
}
/// This method is deliberately called `..._raw`,
/// since the output may possibly include [`TypingMode::ErasedNotCoherence`](TypingMode::ErasedNotCoherence).
/// `ErasedNotCoherence` is an implementation detail of the next trait solver, see its docs for
/// more information.
///
/// `InferCtxt` has two uses: the trait solver calls some methods on it, because the `InferCtxt`
/// works as a kind of store for for example type unification information.
/// `InferCtxt` is also often used outside the trait solver during typeck.
/// There, we don't care about the `ErasedNotCoherence` case and should never encounter it.
/// To make sure these two uses are never confused, we want to statically encode this information.
///
/// The `FnCtxt`, for example, is only used in the outside-trait-solver case. It has a non-raw
/// version of the `typing_mode` method available that asserts `ErasedNotCoherence` is
/// impossible, and returns a `TypingMode` where `ErasedNotCoherence` is made uninhabited using
/// the [`CantBeErased`](rustc_type_ir::CantBeErased) enum. That way you don't even have to
/// match on the variant and can safely ignore it.
///
/// Prefer non-raw apis if available. e.g.,
/// - On the `FnCtxt`
/// - on the `SelectionCtxt`
#[inline(always)]
pub fn disable_trait_solver_fast_paths(&self) -> bool {
self.tcx.disable_trait_solver_fast_paths()
pub fn typing_mode_raw(&self) -> TypingMode<'tcx> {
self.typing_mode
}
#[inline(always)]
pub fn typing_mode(&self) -> TypingMode<'tcx> {
self.typing_mode
pub fn disable_trait_solver_fast_paths(&self) -> bool {
self.tcx.disable_trait_solver_fast_paths()
}
/// Returns the origin of the type variable identified by `vid`.
@@ -1071,7 +1092,7 @@ pub fn opaques_with_sub_unified_hidden_type(&self, ty_vid: TyVid) -> Vec<ty::Ali
#[inline(always)]
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
debug_assert!(!self.next_trait_solver());
match self.typing_mode() {
match self.typing_mode_raw().assert_not_erased() {
TypingMode::Analysis {
defining_opaque_types_and_generators: defining_opaque_types,
}
@@ -1084,7 +1105,7 @@ pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
TypingMode::Coherence
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => false,
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
}
@@ -1403,7 +1424,7 @@ pub fn create_next_universe(&self) -> ty::UniverseIndex {
/// which contains the necessary information to use the trait system without
/// using canonicalization or carrying this inference context around.
pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
let typing_mode = match self.typing_mode() {
let typing_mode = match self.typing_mode_raw() {
// FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible
// to handle them without proper canonicalization. This means we may cause cycle
// errors and fail to reveal opaques while inside of bodies. We should rename this
@@ -1415,7 +1436,7 @@ pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
mode @ (ty::TypingMode::Coherence
| ty::TypingMode::PostBorrowckAnalysis { .. }
| ty::TypingMode::PostAnalysis) => mode,
ty::TypingMode::ErasedNotCoherence => todo!(),
ty::TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
};
ty::TypingEnv::new(param_env, typing_mode)
}
@@ -89,7 +89,7 @@ pub fn handle_opaque_type(
if def_id.is_local() =>
{
let def_id = def_id.expect_local();
if self.typing_mode().is_coherence() {
if self.typing_mode_raw().is_coherence() {
// See comment on `insert_hidden_type` for why this is sufficient in coherence
return Some(self.register_hidden_type(
OpaqueTypeKey { def_id, args },
@@ -229,7 +229,9 @@ pub fn insert_hidden_type(
// value being folded. In simple cases like `-> impl Foo`,
// these are the same span, but not in cases like `-> (impl
// Foo, impl Bar)`.
match self.typing_mode() {
//
// Note: we don't use this function in the next solver so we can safely call `assert_not_erased`
match self.typing_mode_raw().assert_not_erased() {
ty::TypingMode::Coherence => {
// During intercrate we do not define opaque types but instead always
// force ambiguity unless the hidden type is known to not implement
@@ -284,7 +286,6 @@ pub fn insert_hidden_type(
mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => {
bug!("insert hidden type in {mode:?}")
}
ty::TypingMode::ErasedNotCoherence => todo!(),
}
Ok(())
@@ -604,7 +604,7 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
//
// cc trait-system-refactor-initiative#108
if self.infcx.next_trait_solver()
&& !self.infcx.typing_mode().is_coherence()
&& !self.infcx.typing_mode_raw().is_coherence()
&& self.in_alias
{
inner.type_variables().equate(vid, new_var_id);
@@ -736,7 +736,7 @@ fn consts(
// See the comment for type inference variables
// for more details.
if self.infcx.next_trait_solver()
&& !self.infcx.typing_mode().is_coherence()
&& !self.infcx.typing_mode_raw().is_coherence()
&& self.in_alias
{
variable_table.union(vid, new_var_id);
+2 -2
View File
@@ -1063,7 +1063,7 @@ pub fn non_body_analysis(
def_id: impl IntoQueryKey<DefId>,
) -> TypingEnv<'tcx> {
let def_id = def_id.into_query_key();
Self::new(tcx.param_env(def_id), TypingMode::non_body_analysis())
Self::new(tcx.param_env(def_id), TypingMode::non_body_analysis().into())
}
pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey<DefId>) -> TypingEnv<'tcx> {
@@ -1081,7 +1081,7 @@ pub fn with_post_analysis_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx>
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } => {}
TypingMode::PostAnalysis => return self,
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
// No need to reveal opaques with the new solver enabled,
+4 -2
View File
@@ -17,7 +17,9 @@
use rustc_type_ir::TyKind::*;
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::walk::TypeWalker;
use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, TypeVisitableExt, elaborate};
use rustc_type_ir::{
self as ir, BoundVar, CollectAndApply, MayBeErased, TypeVisitableExt, elaborate,
};
use tracing::instrument;
use ty::util::IntTypeExt;
@@ -41,7 +43,7 @@
pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>;
pub type EarlyBinder<'tcx, T> = ir::EarlyBinder<TyCtxt<'tcx>, T>;
pub type Unnormalized<'tcx, T> = ir::Unnormalized<TyCtxt<'tcx>, T>;
pub type TypingMode<'tcx> = ir::TypingMode<TyCtxt<'tcx>>;
pub type TypingMode<'tcx, S = MayBeErased> = ir::TypingMode<TyCtxt<'tcx>, S>;
pub type TypingModeEqWrapper<'tcx> = ir::TypingModeEqWrapper<TyCtxt<'tcx>>;
pub type Placeholder<'tcx, T> = ir::Placeholder<TyCtxt<'tcx>, T>;
pub type PlaceholderRegion<'tcx> = ir::PlaceholderRegion<TyCtxt<'tcx>>;
@@ -7,7 +7,7 @@
use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt, Unnormalized};
use rustc_middle::ty::{self, GenericArg, GenericArgsRef, MayBeErased, Ty, TyCtxt, Unnormalized};
use rustc_middle::{bug, span_bug, traits};
use rustc_span::{DUMMY_SP, Spanned, dummy_spanned};
use tracing::{debug, instrument};
@@ -555,7 +555,7 @@ fn move_paths_for_fields(
| ty::TypingMode::PostBorrowckAnalysis { .. } => {
bug!()
}
ty::TypingMode::ErasedNotCoherence => todo!(),
ty::TypingMode::ErasedNotCoherence(MayBeErased) => unreachable!(),
}
let field_ty = field.ty(tcx, args);
@@ -17,7 +17,7 @@
use rustc_type_ir::relate::solver_relating::RelateExt;
use rustc_type_ir::{
self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner,
TypeFoldable, TypingMode, TypingModeEqWrapper,
MayBeErased, TypeFoldable, TypingMode, TypingModeEqWrapper,
};
use tracing::instrument;
@@ -65,16 +65,16 @@ pub(super) fn canonicalize_goal<D, I>(
D: SolverDelegate<Interner = I>,
I: Interner,
{
let (opaque_types, typing_mode) = match (erase_opaque_types, delegate.typing_mode()) {
let (opaque_types, typing_mode) = match (erase_opaque_types, delegate.typing_mode_raw()) {
// In `TypingMode::Coherence` there should not be any opaques, and we also don't change typing mode.
(_, TypingMode::Coherence) => {
assert!(opaque_types.is_empty());
(&[][..], TypingMode::Coherence)
}
// Make sure we're not recursively in `ErasedNotCoherence`.
(_, TypingMode::ErasedNotCoherence) => {
(_, TypingMode::ErasedNotCoherence(MayBeErased)) => {
assert!(opaque_types.is_empty());
(&[][..], TypingMode::ErasedNotCoherence)
(&[][..], TypingMode::ErasedNotCoherence(MayBeErased))
}
// If we're supposed to erase opaque types, and we're in any typing mode other than coherence,
// do the erasing and change typing mode.
@@ -84,7 +84,7 @@ pub(super) fn canonicalize_goal<D, I>(
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis,
) => (&[][..], TypingMode::ErasedNotCoherence),
) => (&[][..], TypingMode::ErasedNotCoherence(MayBeErased)),
(EraseOpaqueTypes::No, typing_mode) => (opaque_types, typing_mode),
};
@@ -11,9 +11,9 @@
use rustc_type_ir::search_graph::CandidateHeadUsages;
use rustc_type_ir::solve::{AliasBoundKind, MaybeInfo, SizedTraitKind, StalledOnCoroutines};
use rustc_type_ir::{
self as ty, AliasTy, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Unnormalized,
Upcast, elaborate,
self as ty, AliasTy, Interner, MayBeErased, TypeFlags, TypeFoldable, TypeFolder,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
TypingMode, Unnormalized, Upcast, elaborate,
};
use tracing::{debug, instrument};
@@ -478,7 +478,7 @@ pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<D>>(
| CandidateSource::AliasBound(_)
) && has_no_inference_or_external_constraints(c.result)
}),
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
};
if assemble_impls {
self.assemble_impl_candidates(goal, &mut candidates);
@@ -970,7 +970,7 @@ pub(super) fn filter_specialized_impls(
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => {}
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
let mut i = 0;
@@ -1034,7 +1034,7 @@ fn try_assemble_bounds_via_registered_opaques<G: GoalKind<D>>(
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => vec![],
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
};
if opaque_types.is_empty() {
@@ -6,7 +6,7 @@
use rustc_type_ir::lang_items::SolverTraitLangItem;
use rustc_type_ir::solve::inspect::ProbeKind;
use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind};
use rustc_type_ir::{self as ty, Interner, TypingMode, Unnormalized, elaborate};
use rustc_type_ir::{self as ty, Interner, Unnormalized, elaborate};
use tracing::instrument;
use super::assembly::{Candidate, structural_traits};
@@ -8,13 +8,13 @@
use rustc_type_ir::relate::Relate;
use rustc_type_ir::relate::solver_relating::RelateExt;
use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind};
use rustc_type_ir::solve::{AccessedOpaques, AccessedOpaquesInfo, MaybeInfo, OpaqueTypesJank};
use rustc_type_ir::solve::{AccessedOpaques, MaybeInfo, OpaqueTypesJank};
use rustc_type_ir::{
self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable, TypeFolder,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
TypingMode,
};
use tracing::{Level, debug, instrument, trace, warn};
use tracing::{debug, instrument, trace, warn};
use super::has_only_region_constraints;
use crate::canonical::{
@@ -272,7 +272,7 @@ impl<'a, D, I> EvalCtxt<'a, D>
I: Interner,
{
pub(super) fn typing_mode(&self) -> TypingMode<I> {
self.delegate.typing_mode()
self.delegate.typing_mode_raw()
}
/// Computes the `PathKind` for the step from the current goal to the
@@ -24,7 +24,7 @@
use derive_where::derive_where;
use rustc_type_ir::inherent::*;
pub use rustc_type_ir::solve::*;
use rustc_type_ir::{self as ty, Interner, TyVid, TypingMode};
use rustc_type_ir::{self as ty, Interner, MayBeErased, TyVid, TypingMode};
use tracing::instrument;
pub use self::eval_ctxt::{
@@ -368,7 +368,7 @@ fn opaque_type_is_rigid(&self, def_id: I::DefId) -> bool {
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
!def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))
}
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
}
}
@@ -7,7 +7,8 @@
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem};
use rustc_type_ir::{
self as ty, FieldInfo, Interner, NormalizesTo, PredicateKind, Unnormalized, Upcast as _,
self as ty, FieldInfo, Interner, MayBeErased, NormalizesTo, PredicateKind, Unnormalized,
Upcast as _,
};
use tracing::instrument;
@@ -311,7 +312,7 @@ fn consider_impl_candidate(
return ecx
.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
}
ty::TypingMode::ErasedNotCoherence => todo!(),
ty::TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
};
}
Err(guar) => return error_response(ecx, guar),
@@ -349,7 +350,7 @@ fn consider_impl_candidate(
);
return then(ecx, Certainty::Yes);
}
ty::TypingMode::ErasedNotCoherence => todo!(),
ty::TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
} else {
return error_response(ecx, cx.delay_bug("missing item"));
@@ -3,7 +3,7 @@
use rustc_type_ir::inherent::*;
use rustc_type_ir::solve::GoalSource;
use rustc_type_ir::{self as ty, Interner, TypingMode, fold_regions};
use rustc_type_ir::{self as ty, Interner, MayBeErased, TypingMode, fold_regions};
use crate::delegate::SolverDelegate;
use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult};
@@ -97,7 +97,7 @@ pub(super) fn normalize_opaque_type(
TypingMode::Coherence
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => unreachable!(),
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
}
@@ -138,7 +138,7 @@ pub(super) fn normalize_opaque_type(
self.eq(goal.param_env, expected, actual)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
}
}
@@ -3,10 +3,8 @@
use rustc_type_ir::data_structures::ensure_sufficient_stack;
use rustc_type_ir::search_graph::{self, PathKind};
use rustc_type_ir::solve::{
AccessedOpaques, AccessedOpaquesInfo, CanonicalInput, Certainty, NoSolution, QueryResult,
};
use rustc_type_ir::{Interner, TypingMode};
use rustc_type_ir::solve::{AccessedOpaques, CanonicalInput, Certainty, NoSolution, QueryResult};
use rustc_type_ir::{Interner, MayBeErased, TypingMode};
use crate::canonical::response_no_constraints_raw;
use crate::delegate::SolverDelegate;
@@ -72,7 +70,7 @@ fn initial_provisional_result(
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => (Err(NoSolution), AccessedOpaques::default()),
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
},
}
}
@@ -9,8 +9,8 @@
SizedTraitKind,
};
use rustc_type_ir::{
self as ty, FieldInfo, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef,
TypeVisitableExt as _, TypingMode, Unnormalized, Upcast as _, elaborate,
self as ty, FieldInfo, Interner, MayBeErased, Movability, PredicatePolarity, TraitPredicate,
TraitRef, TypeVisitableExt as _, TypingMode, Unnormalized, Upcast as _, elaborate,
};
use tracing::{debug, instrument, trace};
@@ -1396,7 +1396,7 @@ pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Ca
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => {}
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
if candidates
@@ -1575,7 +1575,7 @@ fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>,
| TypingMode::PostAnalysis
| TypingMode::Borrowck { defining_opaque_types: _ }
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
}
@@ -13,7 +13,7 @@
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::Certainty;
use rustc_middle::ty::{
self, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
self, MayBeErased, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
};
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
@@ -288,7 +288,7 @@ fn fetch_eligible_assoc_item(
// and the obligation is monomorphic, otherwise passes such as
// transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations.
match self.typing_mode() {
match self.typing_mode_raw() {
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
@@ -297,7 +297,7 @@ fn fetch_eligible_assoc_item(
let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
!poly_trait_ref.still_further_specializable()
}
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
};
@@ -276,7 +276,7 @@ fn drain_stalled_obligations_for_coroutines(
&mut self,
infcx: &InferCtxt<'tcx>,
) -> PredicateObligations<'tcx> {
let stalled_coroutines = match infcx.typing_mode() {
let stalled_coroutines = match infcx.typing_mode_raw().assert_not_erased() {
TypingMode::Analysis { defining_opaque_types_and_generators } => {
defining_opaque_types_and_generators
}
@@ -284,7 +284,6 @@ fn drain_stalled_obligations_for_coroutines(
| TypingMode::Borrowck { defining_opaque_types: _ }
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ }
| TypingMode::PostAnalysis => return Default::default(),
TypingMode::ErasedNotCoherence => todo!(),
};
if stalled_coroutines.is_empty() {
@@ -25,7 +25,7 @@ pub fn evaluate_host_effect_obligation<'tcx>(
selcx: &mut SelectionContext<'_, 'tcx>,
obligation: &HostEffectObligation<'tcx>,
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
if selcx.infcx.typing_mode().is_coherence() {
if selcx.typing_mode().is_coherence() {
span_bug!(
obligation.cause.span,
"should not select host obligation in old solver in intercrate mode"
@@ -171,7 +171,7 @@ fn drain_stalled_obligations_for_coroutines(
&mut self,
infcx: &InferCtxt<'tcx>,
) -> PredicateObligations<'tcx> {
let stalled_coroutines = match infcx.typing_mode() {
let stalled_coroutines = match infcx.typing_mode_raw().assert_not_erased() {
TypingMode::Analysis { defining_opaque_types_and_generators } => {
defining_opaque_types_and_generators
}
@@ -179,7 +179,6 @@ fn drain_stalled_obligations_for_coroutines(
| TypingMode::Borrowck { defining_opaque_types: _ }
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ }
| TypingMode::PostAnalysis => return Default::default(),
TypingMode::ErasedNotCoherence => todo!(),
};
if stalled_coroutines.is_empty() {
@@ -879,7 +878,7 @@ fn process_trait_obligation(
stalled_on: &mut Vec<TyOrConstInferVar>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let infcx = self.selcx.infcx;
if obligation.predicate.is_global() && !infcx.typing_mode().is_coherence() {
if obligation.predicate.is_global() && !self.selcx.typing_mode().is_coherence() {
// no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too.
if infcx.predicate_must_hold_considering_regions(obligation) {
@@ -933,7 +932,7 @@ fn process_projection_obligation(
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let tcx = self.selcx.tcx();
let infcx = self.selcx.infcx;
if obligation.predicate.is_global() && !infcx.typing_mode().is_coherence() {
if obligation.predicate.is_global() && !self.selcx.typing_mode().is_coherence() {
// no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too.
if infcx.predicate_must_hold_considering_regions(obligation) {
@@ -12,8 +12,8 @@
use rustc_middle::span_bug;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::{
self, AliasTerm, Term, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
TypeVisitableExt, TypingMode, Unnormalized,
self, AliasTerm, MayBeErased, Term, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitable, TypeVisitableExt, TypingMode, Unnormalized,
};
use tracing::{debug, instrument};
@@ -138,14 +138,14 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
// Opaques are treated as rigid outside of `TypingMode::PostAnalysis`,
// so we can ignore those.
match infcx.typing_mode() {
match infcx.typing_mode_raw() {
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE),
TypingMode::PostAnalysis => {}
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => unreachable!(),
}
value.has_type_flags(flags)
@@ -411,7 +411,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
match data.kind {
ty::Opaque { def_id } => {
// Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.selcx.infcx.typing_mode() {
match self.selcx.typing_mode() {
// FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
TypingMode::Coherence
| TypingMode::Analysis { .. }
@@ -436,7 +436,6 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
self.depth -= 1;
folded_ty
}
TypingMode::ErasedNotCoherence => todo!(),
}
}
@@ -950,7 +950,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// and the obligation is monomorphic, otherwise passes such as
// transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations.
match selcx.infcx.typing_mode() {
match selcx.typing_mode() {
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
@@ -969,7 +969,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
selcx.infcx.resolve_vars_if_possible(trait_ref);
!poly_trait_ref.still_further_specializable()
}
TypingMode::ErasedNotCoherence => todo!(),
}
}
}
@@ -215,7 +215,7 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
let res = match data.kind {
ty::Opaque { def_id } => {
// Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.infcx.typing_mode() {
match self.infcx.typing_mode_raw().assert_not_erased() {
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
@@ -253,7 +253,6 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
self.anon_depth -= 1;
folded_ty?
}
TypingMode::ErasedNotCoherence => todo!(),
}
}
@@ -849,7 +849,7 @@ fn assemble_candidates_from_auto_impls(
//
// Note that this is only sound as projection candidates of opaque types
// are always applicable for auto traits.
} else if self.infcx.typing_mode().is_coherence() {
} else if self.typing_mode().is_coherence() {
// We do not emit auto trait candidates for opaque types in coherence.
// Doing so can result in weird dependency cycles.
candidates.ambiguous = true;
@@ -26,9 +26,9 @@
use rustc_middle::ty::error::TypeErrorToStringExt;
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
use rustc_middle::ty::{
self, CandidatePreferenceMode, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate,
SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast,
elaborate, may_use_unstable_feature,
self, CandidatePreferenceMode, CantBeErased, DeepRejectCtxt, GenericArgsRef,
PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
TypingMode, Unnormalized, Upcast, elaborate, may_use_unstable_feature,
};
use rustc_next_trait_solver::solve::AliasBoundKind;
use rustc_span::Symbol;
@@ -199,6 +199,10 @@ pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
}
}
pub fn typing_mode(&self) -> TypingMode<'tcx, CantBeErased> {
self.infcx.typing_mode_raw().assert_not_erased()
}
pub fn with_query_mode(
infcx: &'cx InferCtxt<'tcx>,
query_mode: TraitQueryMode,
@@ -210,7 +214,7 @@ pub fn with_query_mode(
/// Enables tracking of intercrate ambiguity causes. See
/// the documentation of [`Self::intercrate_ambiguity_causes`] for more.
pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
assert!(self.infcx.typing_mode().is_coherence());
assert!(self.typing_mode().is_coherence());
assert!(self.intercrate_ambiguity_causes.is_none());
self.intercrate_ambiguity_causes = Some(FxIndexSet::default());
@@ -223,7 +227,7 @@ pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
pub fn take_intercrate_ambiguity_causes(
&mut self,
) -> FxIndexSet<IntercrateAmbiguityCause<'tcx>> {
assert!(self.infcx.typing_mode().is_coherence());
assert!(self.typing_mode().is_coherence());
self.intercrate_ambiguity_causes.take().unwrap_or_default()
}
@@ -1022,7 +1026,7 @@ fn evaluate_trait_predicate_recursively<'o>(
previous_stack: TraitObligationStackList<'o, 'tcx>,
mut obligation: PolyTraitObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
if !self.infcx.typing_mode().is_coherence()
if !self.typing_mode().is_coherence()
&& obligation.is_global()
&& obligation.param_env.caller_bounds().iter().all(|bound| bound.has_param())
{
@@ -1479,13 +1483,12 @@ fn filter_reservation_impls(
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {
let obligation = &stack.obligation;
match self.infcx.typing_mode() {
match self.typing_mode() {
TypingMode::Coherence => {}
TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => return Ok(()),
TypingMode::ErasedNotCoherence => todo!(),
}
debug!("is_knowable()");
@@ -1513,7 +1516,7 @@ fn can_use_global_caches(
return false;
}
match self.infcx.typing_mode() {
match self.typing_mode() {
// Avoid using the global cache during coherence and just rely
// on the local cache. It is really just a simplification to
// avoid us having to fear that coherence results "pollute"
@@ -1545,7 +1548,6 @@ fn can_use_global_caches(
// FIXME(#132279): This is still incorrect as we treat opaque types
// and default associated items differently between these two modes.
TypingMode::PostAnalysis => true,
TypingMode::ErasedNotCoherence => todo!(),
}
}
@@ -2567,7 +2569,7 @@ fn match_impl(
nested_obligations.extend(obligations);
if impl_trait_header.polarity == ty::ImplPolarity::Reservation
&& !self.infcx.typing_mode().is_coherence()
&& !self.typing_mode().is_coherence()
{
debug!("reservation impls only apply in intercrate mode");
return Err(());
@@ -2906,7 +2908,7 @@ fn impl_or_trait_obligations(
}
pub(super) fn should_stall_coroutine(&self, def_id: DefId) -> bool {
match self.infcx.typing_mode() {
match self.typing_mode() {
TypingMode::Analysis { defining_opaque_types_and_generators: stalled_generators } => {
def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
}
@@ -2914,7 +2916,6 @@ pub(super) fn should_stall_coroutine(&self, def_id: DefId) -> bool {
| TypingMode::PostAnalysis
| TypingMode::Borrowck { defining_opaque_types: _ }
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => false,
TypingMode::ErasedNotCoherence => todo!(),
}
}
}
+3 -3
View File
@@ -6,8 +6,8 @@
use rustc_middle::query::Providers;
use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError};
use rustc_middle::ty::{
self, ClosureKind, GenericArgsRef, Instance, PseudoCanonicalInput, TyCtxt, TypeVisitableExt,
Unnormalized,
self, ClosureKind, GenericArgsRef, Instance, MayBeErased, PseudoCanonicalInput, TyCtxt,
TypeVisitableExt, Unnormalized,
};
use rustc_span::sym;
use rustc_trait_selection::traits;
@@ -161,7 +161,7 @@ fn resolve_associated_item<'tcx>(
| ty::TypingMode::Borrowck { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. } => false,
ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(),
ty::TypingMode::ErasedNotCoherence => todo!(),
ty::TypingMode::ErasedNotCoherence(MayBeErased) => unreachable!(),
}
};
if !eligible {
+78 -11
View File
@@ -1,3 +1,4 @@
use core::fmt;
use std::hash::{Hash, Hasher};
use derive_where::derive_where;
@@ -11,6 +12,26 @@
use crate::solve::VisibleForLeakCheck;
use crate::{self as ty, Interner, TyVid};
mod private {
pub trait Sealed {}
impl Sealed for super::CantBeErased {}
impl Sealed for super::MayBeErased {}
}
pub trait TypingModeErasedStatus: private::Sealed + Clone + Copy + Hash + fmt::Debug {}
#[derive(Clone, Copy, Hash, Debug)]
pub enum CantBeErased {}
#[derive(Clone, Copy, Hash, Debug)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
)]
pub struct MayBeErased;
impl TypingModeErasedStatus for CantBeErased {}
impl TypingModeErasedStatus for MayBeErased {}
/// The current typing mode of an inference context. We unfortunately have some
/// slightly different typing rules depending on the current context. See the
/// doc comment for each variant for how and why they are used.
@@ -42,8 +63,7 @@
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext)
)]
#[cfg_attr(feature = "nightly", rustc_must_match_exhaustively)]
pub enum TypingMode<I: Interner> {
pub enum TypingMode<I: Interner, S: TypingModeErasedStatus = MayBeErased> {
/// When checking whether impls overlap, we check whether any obligations
/// are guaranteed to never hold when unifying the impls. This requires us
/// to be complete: we must never fail to prove something which may actually
@@ -121,7 +141,7 @@ pub enum TypingMode<I: Interner> {
/// rerun in the original typing mode.
///
/// `TypingMode::Coherence` is not replaced by this and is always kept as-is.
ErasedNotCoherence,
ErasedNotCoherence(S),
}
/// We want to highly discourage using equality checks on typing modes.
@@ -134,7 +154,7 @@ pub enum TypingMode<I: Interner> {
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext)
)]
pub struct TypingModeEqWrapper<I: Interner>(pub TypingMode<I>);
pub struct TypingModeEqWrapper<I: Interner>(pub TypingMode<I, MayBeErased>);
impl<I: Interner> Hash for TypingModeEqWrapper<I> {
fn hash<H: Hasher>(&self, state: &mut H) {
@@ -159,14 +179,17 @@ fn eq(&self, other: &Self) -> bool {
TypingMode::PostBorrowckAnalysis { defined_opaque_types: r },
) => l == r,
(TypingMode::PostAnalysis, TypingMode::PostAnalysis) => true,
(TypingMode::ErasedNotCoherence, TypingMode::ErasedNotCoherence) => true,
(
TypingMode::ErasedNotCoherence(MayBeErased),
TypingMode::ErasedNotCoherence(MayBeErased),
) => true,
(
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis
| TypingMode::ErasedNotCoherence,
| TypingMode::ErasedNotCoherence(MayBeErased),
_,
) => false,
}
@@ -175,7 +198,7 @@ fn eq(&self, other: &Self) -> bool {
impl<I: Interner> Eq for TypingModeEqWrapper<I> {}
impl<I: Interner> TypingMode<I> {
impl<I: Interner, S: TypingModeErasedStatus> TypingMode<I, S> {
/// There are a bunch of places in the compiler where we single out `Coherence`,
/// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
/// but not having this method leads to a bunch of noisy code.
@@ -188,10 +211,37 @@ pub fn is_coherence(&self) -> bool {
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis
| TypingMode::ErasedNotCoherence => false,
| TypingMode::ErasedNotCoherence(_) => false,
}
}
}
impl<I: Interner> TypingMode<I, MayBeErased> {
/// Only call this when you're sure you're outside the next trait solver!
/// That means either not in the trait solver, or in code that is old-solver only.
///
/// See the comment on `InferCtxt::typing_mode_raw`
pub fn assert_not_erased(self) -> TypingMode<I, CantBeErased> {
match self {
TypingMode::Coherence => TypingMode::Coherence,
TypingMode::Analysis { defining_opaque_types_and_generators } => {
TypingMode::Analysis { defining_opaque_types_and_generators }
}
TypingMode::Borrowck { defining_opaque_types } => {
TypingMode::Borrowck { defining_opaque_types }
}
TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
TypingMode::PostBorrowckAnalysis { defined_opaque_types }
}
TypingMode::PostAnalysis => TypingMode::PostAnalysis,
TypingMode::ErasedNotCoherence(MayBeErased) => panic!(
"Called `assert_not_erased` from a place that can be called by the trait solver in `TypingMode::ErasedNotCoherence`. `TypingMode` is `ErasedNotCoherence` in a place where that should be impossible"
),
}
}
}
impl<I: Interner> TypingMode<I, CantBeErased> {
/// Analysis outside of a body does not define any opaque types.
pub fn non_body_analysis() -> TypingMode<I> {
TypingMode::Analysis { defining_opaque_types_and_generators: Default::default() }
@@ -234,6 +284,24 @@ pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I
}
}
impl<I: Interner> From<TypingMode<I, CantBeErased>> for TypingMode<I, MayBeErased> {
fn from(value: TypingMode<I, CantBeErased>) -> Self {
match value {
TypingMode::Coherence => TypingMode::Coherence,
TypingMode::Analysis { defining_opaque_types_and_generators } => {
TypingMode::Analysis { defining_opaque_types_and_generators }
}
TypingMode::Borrowck { defining_opaque_types } => {
TypingMode::Borrowck { defining_opaque_types }
}
TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
TypingMode::PostBorrowckAnalysis { defined_opaque_types }
}
TypingMode::PostAnalysis => TypingMode::PostAnalysis,
}
}
}
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
pub trait InferCtxtLike: Sized {
type Interner: Interner;
@@ -249,7 +317,7 @@ fn next_trait_solver(&self) -> bool {
fn disable_trait_solver_fast_paths(&self) -> bool;
fn typing_mode(&self) -> TypingMode<Self::Interner>;
fn typing_mode_raw(&self) -> TypingMode<Self::Interner>;
fn universe(&self) -> ty::UniverseIndex;
fn create_next_universe(&self) -> ty::UniverseIndex;
@@ -425,7 +493,7 @@ pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
// Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
// if we are in std/core even if there is a corresponding `feature` attribute on the crate.
match infcx.typing_mode() {
match infcx.typing_mode_raw().assert_not_erased() {
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
@@ -433,6 +501,5 @@ pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
infcx.cx().features().feature_bound_holds_in_crate(symbol)
}
TypingMode::PostAnalysis => true,
TypingMode::ErasedNotCoherence => todo!(),
}
}
+2 -2
View File
@@ -131,7 +131,7 @@ pub fn super_combine_tys<Infcx, I, R>(
(ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }), _)
| (_, ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. })) => {
assert!(!infcx.next_trait_solver());
match infcx.typing_mode() {
match infcx.typing_mode_raw().assert_not_erased() {
// During coherence, opaque types should be treated as *possibly*
// equal to any other type. This is an
// extremely heavy hammer, but can be relaxed in a forwards-compatible
@@ -144,7 +144,7 @@ pub fn super_combine_tys<Infcx, I, R>(
| TypingMode::Borrowck { .. }
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b),
TypingMode::ErasedNotCoherence => todo!(),
TypingMode::ErasedNotCoherence(MayBeErased) => todo!(),
}
}