From 630f0d2bbbdb18bce35169a135a0654a1e6a9bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Mon, 13 Apr 2026 13:37:51 +0200 Subject: [PATCH] type safety for typing mode outside trait solver which can't be erased-not-coherence --- .../src/const_eval/eval_queries.rs | 4 +- .../src/const_eval/valtrees.rs | 4 +- .../src/interpret/eval_context.rs | 6 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 10 ++- .../src/infer/canonical/canonicalizer.rs | 2 +- compiler/rustc_infer/src/infer/context.rs | 4 +- compiler/rustc_infer/src/infer/mod.rs | 37 ++++++-- .../rustc_infer/src/infer/opaque_types/mod.rs | 7 +- .../src/infer/relate/generalize.rs | 4 +- compiler/rustc_middle/src/ty/mod.rs | 4 +- compiler/rustc_middle/src/ty/sty.rs | 6 +- .../rustc_mir_transform/src/elaborate_drop.rs | 4 +- .../src/canonical/mod.rs | 10 +-- .../src/solve/assembly/mod.rs | 12 +-- .../src/solve/effect_goals.rs | 2 +- .../src/solve/eval_ctxt/mod.rs | 6 +- .../rustc_next_trait_solver/src/solve/mod.rs | 4 +- .../src/solve/normalizes_to/mod.rs | 7 +- .../src/solve/normalizes_to/opaque_types.rs | 6 +- .../src/solve/search_graph.rs | 8 +- .../src/solve/trait_goals.rs | 8 +- .../src/solve/delegate.rs | 6 +- .../src/solve/fulfill.rs | 3 +- .../src/traits/effects.rs | 2 +- .../src/traits/fulfill.rs | 7 +- .../src/traits/normalize.rs | 11 ++- .../src/traits/project.rs | 3 +- .../src/traits/query/normalize.rs | 3 +- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/mod.rs | 27 +++--- compiler/rustc_ty_utils/src/instance.rs | 6 +- compiler/rustc_type_ir/src/infer_ctxt.rs | 89 ++++++++++++++++--- compiler/rustc_type_ir/src/relate/combine.rs | 4 +- 33 files changed, 206 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 8d618485c8ee..7f0d6c8e8734 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -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. diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 2bfce2f945ce..3858a3b7047d 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -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))?; diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 53b9be71bc52..06410df7e1f1 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -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!(), } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 63bd49f08030..5fea7454e57e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -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() } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index a575ba79df45..e0adcfc06a0e 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -72,7 +72,7 @@ pub fn canonicalize_query( 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 diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 0dc1f5e5eec5..8107d91ba410 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -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 { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 6174927df6ec..2ccdd317f05c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -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) -> 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) -> 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) } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index a3926a0dd23d..6b051f42421b 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -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(()) diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 5ec56b3e9dc4..3d2d617cfdb2 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -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); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4cf8aa091ca1..bf35668950b5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1063,7 +1063,7 @@ pub fn non_body_analysis( def_id: impl IntoQueryKey, ) -> 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) -> 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, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5360a123a419..112ad65e19bf 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -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, T>; pub type EarlyBinder<'tcx, T> = ir::EarlyBinder, T>; pub type Unnormalized<'tcx, T> = ir::Unnormalized, T>; -pub type TypingMode<'tcx> = ir::TypingMode>; +pub type TypingMode<'tcx, S = MayBeErased> = ir::TypingMode, S>; pub type TypingModeEqWrapper<'tcx> = ir::TypingModeEqWrapper>; pub type Placeholder<'tcx, T> = ir::Placeholder, T>; pub type PlaceholderRegion<'tcx> = ir::PlaceholderRegion>; diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 69c1e676466f..48006bace447 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -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); diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index cd65cd0cc186..8de84247c8ca 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -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: SolverDelegate, 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( | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis, - ) => (&[][..], TypingMode::ErasedNotCoherence), + ) => (&[][..], TypingMode::ErasedNotCoherence(MayBeErased)), (EraseOpaqueTypes::No, typing_mode) => (opaque_types, typing_mode), }; diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 910c943dfec0..b5e5109c6b79 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -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>( | 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>( | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => vec![], - TypingMode::ErasedNotCoherence => todo!(), + TypingMode::ErasedNotCoherence(MayBeErased) => todo!(), }; if opaque_types.is_empty() { diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index b7fbdb70864b..508287a4dfee 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -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}; diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 03b3e34f43e6..2813f23d489f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -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 { - self.delegate.typing_mode() + self.delegate.typing_mode_raw() } /// Computes the `PathKind` for the step from the current goal to the diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 82189e53fcd4..b50e686606e0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -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!(), } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 35c0910ae677..d6383cb48fa9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -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")); diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index a1e7246eee6c..98c0c7eadb5b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -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!(), } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index 877e3dfaad0b..9e09d3cd019a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -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!(), }, } } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 01954bc744e5..5934b01f96e1 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -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 {} - TypingMode::ErasedNotCoherence => todo!(), + TypingMode::ErasedNotCoherence(MayBeErased) => todo!(), } if candidates @@ -1575,7 +1575,7 @@ fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option, | TypingMode::PostAnalysis | TypingMode::Borrowck { defining_opaque_types: _ } | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {} - TypingMode::ErasedNotCoherence => todo!(), + TypingMode::ErasedNotCoherence(MayBeErased) => todo!(), } } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 382158901e29..4bea60521178 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -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!(), } }; diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 0c6e091235b3..ed345d98b539 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -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() { diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index 0f36edcdd830..a4691c6aa438 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -25,7 +25,7 @@ pub fn evaluate_host_effect_obligation<'tcx>( selcx: &mut SelectionContext<'_, 'tcx>, obligation: &HostEffectObligation<'tcx>, ) -> Result>, 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" diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index f34500c5dd2e..ce8f05637f9a 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -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, ) -> ProcessResult, 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, 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) { diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 5f866af0f774..6e526e8dc548 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -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>>( // 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!(), } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 91713c210845..e2458a2392f5 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -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!(), } } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index d373cd772b57..e8c5d10c78ce 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -215,7 +215,7 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, 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, Self::Error> { self.anon_depth -= 1; folded_ty? } - TypingMode::ErasedNotCoherence => todo!(), } } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index f7614e7c9730..3b599db8ff1c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -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; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f980f7ee00a2..fc208ceaf609 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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> { - 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 { - 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!(), } } } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 0ac2899165f2..178533fb231a 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -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 { diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 5d4326d22eb9..c9533623591a 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -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 { +pub enum TypingMode { /// 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 { /// 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 { feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext) )] -pub struct TypingModeEqWrapper(pub TypingMode); +pub struct TypingModeEqWrapper(pub TypingMode); impl Hash for TypingModeEqWrapper { fn hash(&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 Eq for TypingModeEqWrapper {} -impl TypingMode { +impl TypingMode { /// 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 TypingMode { + /// 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 { + 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 TypingMode { /// Analysis outside of a body does not define any opaque types. pub fn non_body_analysis() -> TypingMode { 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 From> for TypingMode { + fn from(value: TypingMode) -> 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; + fn typing_mode_raw(&self) -> TypingMode; 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!(), } } diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 3f7b8f9e6c84..7e4b95580a8e 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -131,7 +131,7 @@ pub fn super_combine_tys( (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( | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b), - TypingMode::ErasedNotCoherence => todo!(), + TypingMode::ErasedNotCoherence(MayBeErased) => todo!(), } }