diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 2f632f750b761..16c75b781dbec 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -23,8 +23,10 @@ use rustc_span::{BytePos, DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::regions::InferCtxtRegionExt; +use rustc_trait_selection::solve::NextSolverError; use rustc_trait_selection::traits::{ - self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, + self, FromSolverError, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, + OldSolverError, }; use tracing::{debug, instrument}; @@ -801,10 +803,7 @@ struct ImplTraitInTraitCollector<'a, 'tcx, E> { impl_m_id: LocalDefId, } -impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E> -where - E: 'tcx, -{ +impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E> { fn new( ocx: &'a ObligationCtxt<'a, 'tcx, E>, span: Span, @@ -817,7 +816,7 @@ where impl<'tcx, E> TypeFolder> for ImplTraitInTraitCollector<'_, 'tcx, E> where - E: 'tcx, + E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>, { fn cx(&self) -> TyCtxt<'tcx> { self.ocx.infcx.tcx diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 0e34a6120b609..e753100a5e1a9 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::{self, FloatVid, Ty, TyCtxt, TypeSuperVisitable, TypeVisit use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::{DUMMY_SP, Span}; -use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; +use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt, TraitEngine}; use tracing::debug; use crate::{FnCtxt, diagnostics}; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 9a1b1f8300957..7d11beb7722b0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -37,7 +37,7 @@ use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; use rustc_trait_selection::traits::{ - self, NormalizeExt, ObligationCauseCode, StructurallyNormalizeExt, + self, NormalizeExt, ObligationCauseCode, StructurallyNormalizeExt, TraitEngine, }; use tracing::{debug, instrument}; @@ -1499,7 +1499,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // in a reentrant borrow, causing an ICE. let result = self.at(&self.misc(sp), self.param_env).structurally_normalize_const( Unnormalized::new_wip(ct), - &mut **self.fulfillment_cx.borrow_mut(), + &mut *self.fulfillment_cx.borrow_mut(), ); match result { Ok(normalized_ct) => normalized_ct, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index cfaa60231379e..b7fac3e2b993c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -9,6 +9,7 @@ use rustc_trait_selection::solve::Certainty; use rustc_trait_selection::solve::inspect::{ InferCtxtProofTreeExt, InspectConfig, InspectGoal, ProofTreeVisitor, }; +use rustc_trait_selection::traits::TraitEngine; use tracing::{debug, instrument, trace}; use crate::FnCtxt; diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index dce7f0bd67794..73f4daeaa869b 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -57,6 +57,7 @@ use rustc_middle::{bug, span_bug}; use rustc_session::config; use rustc_span::Span; use rustc_span::def_id::LocalDefId; +use rustc_trait_selection::traits::TraitEngine; use tracing::{debug, instrument}; use typeck_root_ctxt::TypeckRootCtxt; diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index e4dcead1f7954..30e796b133f25 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -8,7 +8,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty, TyCtxt, TyVid, TypeVisitableExt, TypingMode}; use rustc_span::Span; use rustc_span::def_id::LocalDefIdMap; -use rustc_trait_selection::traits::{self, FulfillmentError, TraitEngine, TraitEngineExt as _}; +use rustc_trait_selection::traits::{self, DualFulfillmentCtxt, FulfillmentError, TraitEngine}; use tracing::instrument; use super::callee::DeferredCallResolution; @@ -31,7 +31,7 @@ pub(crate) struct TypeckRootCtxt<'tcx> { pub(super) locals: RefCell>>, - pub(super) fulfillment_cx: RefCell>>>, + pub(super) fulfillment_cx: RefCell>>, // Used to detect opaque types uses added after we've already checked them. // @@ -85,7 +85,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> { .in_hir_typeck() .build(TypingMode::typeck_for_body(tcx, def_id)); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); - let fulfillment_cx = RefCell::new(>::new(&infcx)); + let fulfillment_cx = RefCell::new(DualFulfillmentCtxt::new(&infcx)); TypeckRootCtxt { infcx, diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 38fc991fcfeb6..be93d7cc58877 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -33,7 +33,7 @@ impl<'tcx> ScrubbedTraitError<'tcx> { } } -pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { +pub trait TraitEngine<'tcx, E>: 'tcx { /// Requires that `ty` must implement the trait with `def_id` in /// the given environment. This trait must not have any type /// parameters (except for `Self`). diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 3b1a64a7e80bb..609cbca4ba7ee 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -690,14 +690,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.specializes((impl_def_id, victim_def_id)) } + #[inline] fn impl_is_default(self, impl_def_id: DefId) -> bool { self.defaultness(impl_def_id).is_default() } + #[inline] fn impl_trait_ref(self, impl_def_id: DefId) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> { self.impl_trait_ref(impl_def_id) } + #[inline] fn impl_polarity(self, impl_def_id: DefId) -> ty::ImplPolarity { self.impl_polarity(impl_def_id) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 4c2c92ebc5072..6c3214fcc0bc0 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -37,7 +37,7 @@ type PendingObligations<'tcx> = /// /// It is also likely that we want to use slightly different datastructures /// here as this will have to deal with far more root goals than `evaluate_all`. -pub struct FulfillmentCtxt<'tcx, E: 'tcx> { +pub struct FulfillmentCtxt<'tcx, E> { obligations: ObligationStorage<'tcx>, /// The snapshot in which this context was created. Using the context diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 1990ebd913eca..327576bfcae4a 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -10,12 +10,11 @@ use rustc_infer::infer::canonical::{ }; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, TypeTrace}; use rustc_infer::traits::PredicateObligations; -use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::Relate; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Unnormalized, Upcast, Variance}; +use rustc_middle::ty::{self, Ty, TyCtxt, TyVid, TypeFoldable, Unnormalized, Upcast, Variance}; use super::{FromSolverError, FulfillmentContext, ScrubbedTraitError, TraitEngine}; use crate::error_reporting::InferCtxtErrorExt; @@ -27,20 +26,95 @@ use crate::traits::{ StructurallyNormalizeExt, }; -#[extension(pub trait TraitEngineExt<'tcx, E>)] -impl<'tcx, E> dyn TraitEngine<'tcx, E> +/// An enum that lets us switch between the old and new solvers. +pub enum DualFulfillmentCtxt<'tcx, E> { + Old(FulfillmentContext<'tcx, E>), + Next(NextFulfillmentCtxt<'tcx, E>), +} + +impl<'tcx, E> DualFulfillmentCtxt<'tcx, E> where - E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>, + E: FromSolverError<'tcx, OldSolverError<'tcx>>, { - fn new(infcx: &InferCtxt<'tcx>) -> Box { + #[inline] + pub fn new(infcx: &InferCtxt<'tcx>) -> Self { if infcx.next_trait_solver() { - Box::new(NextFulfillmentCtxt::new(infcx)) + DualFulfillmentCtxt::Next(NextFulfillmentCtxt::new(infcx)) } else { assert!( !infcx.tcx.next_trait_solver_globally(), "using old solver even though new solver is enabled globally" ); - Box::new(FulfillmentContext::new(infcx)) + DualFulfillmentCtxt::Old(FulfillmentContext::new(infcx)) + } + } +} + +impl<'tcx, E> TraitEngine<'tcx, E> for DualFulfillmentCtxt<'tcx, E> +where + E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>, +{ + fn register_predicate_obligation( + &mut self, + infcx: &InferCtxt<'tcx>, + obligation: PredicateObligation<'tcx>, + ) { + match self { + DualFulfillmentCtxt::Old(cx) => cx.register_predicate_obligation(infcx, obligation), + DualFulfillmentCtxt::Next(cx) => cx.register_predicate_obligation(infcx, obligation), + } + } + + fn try_evaluate_obligations(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { + match self { + DualFulfillmentCtxt::Old(cx) => cx.try_evaluate_obligations(infcx), + DualFulfillmentCtxt::Next(cx) => cx.try_evaluate_obligations(infcx), + } + } + + fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { + match self { + DualFulfillmentCtxt::Old(cx) => cx.collect_remaining_errors(infcx), + DualFulfillmentCtxt::Next(cx) => cx.collect_remaining_errors(infcx), + } + } + + fn has_pending_obligations(&self) -> bool { + match self { + DualFulfillmentCtxt::Old(cx) => cx.has_pending_obligations(), + DualFulfillmentCtxt::Next(cx) => cx.has_pending_obligations(), + } + } + + fn pending_obligations(&self) -> PredicateObligations<'tcx> { + match self { + DualFulfillmentCtxt::Old(cx) => cx.pending_obligations(), + DualFulfillmentCtxt::Next(cx) => cx.pending_obligations(), + } + } + + fn pending_obligations_potentially_referencing_sub_root( + &self, + infcx: &InferCtxt<'tcx>, + sub_root: TyVid, + ) -> PredicateObligations<'tcx> { + match self { + DualFulfillmentCtxt::Old(cx) => { + cx.pending_obligations_potentially_referencing_sub_root(infcx, sub_root) + } + DualFulfillmentCtxt::Next(cx) => { + cx.pending_obligations_potentially_referencing_sub_root(infcx, sub_root) + } + } + } + + fn drain_stalled_obligations_for_coroutines( + &mut self, + infcx: &InferCtxt<'tcx>, + ) -> PredicateObligations<'tcx> { + match self { + DualFulfillmentCtxt::Old(cx) => cx.drain_stalled_obligations_for_coroutines(infcx), + DualFulfillmentCtxt::Next(cx) => cx.drain_stalled_obligations_for_coroutines(infcx), } } } @@ -49,24 +123,26 @@ where /// with obligations outside of hir or mir typeck. pub struct ObligationCtxt<'a, 'tcx, E = ScrubbedTraitError<'tcx>> { pub infcx: &'a InferCtxt<'tcx>, - engine: RefCell>>, + engine: RefCell>, } impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>> { + #[inline] pub fn new_with_diagnostics(infcx: &'a InferCtxt<'tcx>) -> Self { - Self { infcx, engine: RefCell::new(>::new(infcx)) } + Self { infcx, engine: RefCell::new(DualFulfillmentCtxt::new(infcx)) } } } impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, ScrubbedTraitError<'tcx>> { + #[inline] pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - Self { infcx, engine: RefCell::new(>::new(infcx)) } + Self { infcx, engine: RefCell::new(DualFulfillmentCtxt::new(infcx)) } } } impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E> where - E: 'tcx, + E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>, { pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) { self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation); @@ -297,14 +373,14 @@ impl<'tcx> ObligationCtxt<'_, 'tcx, ScrubbedTraitError<'tcx>> { self.infcx.make_canonicalized_query_response( inference_vars, answer, - &mut **self.engine.borrow_mut(), + &mut *self.engine.borrow_mut(), ) } } impl<'tcx, E> ObligationCtxt<'_, 'tcx, E> where - E: FromSolverError<'tcx, NextSolverError<'tcx>>, + E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>, { pub fn assumed_wf_types( &self, @@ -331,7 +407,7 @@ where match self .infcx .at(&cause, param_env) - .deeply_normalize(Unnormalized::new_wip(ty), &mut **self.engine.borrow_mut()) + .deeply_normalize(Unnormalized::new_wip(ty), &mut *self.engine.borrow_mut()) { // Insert well-formed types, ignoring duplicates. Ok(normalized) => drop(implied_bounds.insert(normalized)), @@ -348,7 +424,7 @@ where param_env: ty::ParamEnv<'tcx>, value: Unnormalized<'tcx, T>, ) -> Result> { - self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut()) + self.infcx.at(cause, param_env).deeply_normalize(value, &mut *self.engine.borrow_mut()) } pub fn structurally_normalize_ty( @@ -359,7 +435,7 @@ where ) -> Result, Vec> { self.infcx .at(cause, param_env) - .structurally_normalize_ty(value, &mut **self.engine.borrow_mut()) + .structurally_normalize_ty(value, &mut *self.engine.borrow_mut()) } pub fn structurally_normalize_const( @@ -370,7 +446,7 @@ where ) -> Result, Vec> { self.infcx .at(cause, param_env) - .structurally_normalize_const(value, &mut **self.engine.borrow_mut()) + .structurally_normalize_const(value, &mut *self.engine.borrow_mut()) } pub fn structurally_normalize_term( @@ -381,6 +457,6 @@ where ) -> Result, Vec> { self.infcx .at(cause, param_env) - .structurally_normalize_term(value, &mut **self.engine.borrow_mut()) + .structurally_normalize_term(value, &mut *self.engine.borrow_mut()) } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 95f0c3dc9881d..3a14dc0aa4040 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -57,7 +57,7 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { /// along. Once all type inference constraints have been generated, the /// method `evaluate_obligations_error_on_ambiguity` can be used to report any remaining /// ambiguous cases as errors. -pub struct FulfillmentContext<'tcx, E: 'tcx> { +pub struct FulfillmentContext<'tcx, E> { /// A list of all obligations that have been registered with this /// fulfillment context. predicates: ObligationForest>, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index d3262bd6a6f96..f1e2d031bc040 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -50,7 +50,7 @@ pub use self::dyn_compatibility::{ DynCompatibilityViolation, dyn_compatibility_violations_for_assoc_item, hir_ty_lowering_dyn_compatibility_violations, is_vtable_safe_method, }; -pub use self::engine::{ObligationCtxt, TraitEngineExt}; +pub use self::engine::{DualFulfillmentCtxt, ObligationCtxt}; pub use self::fulfill::{FulfillmentContext, OldSolverError, PendingPredicateObligation}; pub use self::normalize::NormalizeExt; pub use self::project::{normalize_inherent_projection, normalize_projection_term}; diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index a9ed6126ea752..dee141e283a08 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -6,6 +6,7 @@ use rustc_span::Span; use tracing::{debug, instrument}; use crate::solve::NextSolverError; +use crate::traits::fulfill::OldSolverError; use crate::traits::query::NoSolution; use crate::traits::query::normalize::QueryNormalizeExt; use crate::traits::{FromSolverError, Normalized, ObligationCause, ObligationCtxt}; @@ -106,7 +107,7 @@ pub fn compute_dropck_outlives_with_errors<'tcx, E>( span: Span, ) -> Result, Vec> where - E: FromSolverError<'tcx, NextSolverError<'tcx>>, + E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>, { let tcx = ocx.infcx.tcx; let ParamEnvAnd { param_env, value: DropckOutlives { dropped_ty } } = goal; diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 9b50657b6b8b1..e91ef8333d99e 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -208,6 +208,7 @@ impl