diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 359b9da11ced6..be8d29abff713 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -89,6 +89,45 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) } + #[allow(rustc::usage_of_type_ir_traits)] + fn is_changed_arg(&self, arg: ty::GenericArg<'tcx>) -> bool { + match arg.unpack() { + ty::GenericArgKind::Lifetime(lt) => { + if let ty::ReVar(vid) = lt.kind() { + self.opportunistic_resolve_lt_var(vid) != lt + } else { + true + } + } + ty::GenericArgKind::Type(ty) => { + if let ty::Infer(infer_ty) = *ty.kind() { + match infer_ty { + ty::InferTy::TyVar(vid) => self.opportunistic_resolve_ty_var(vid) != ty, + ty::InferTy::IntVar(vid) => self.opportunistic_resolve_int_var(vid) != ty, + ty::InferTy::FloatVar(vid) => { + self.opportunistic_resolve_float_var(vid) != ty + } + ty::InferTy::FreshTy(_) + | ty::InferTy::FreshIntTy(_) + | ty::InferTy::FreshFloatTy(_) => true, + } + } else { + true + } + } + ty::GenericArgKind::Const(ct) => { + if let ty::ConstKind::Infer(infer_ct) = ct.kind() { + match infer_ct { + ty::InferConst::Var(vid) => self.opportunistic_resolve_ct_var(vid) != ct, + ty::InferConst::Fresh(_) => true, + } + } else { + true + } + } + } + } + fn next_region_infer(&self) -> ty::Region<'tcx> { self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP)) } @@ -221,6 +260,9 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries { self.inner.borrow_mut().opaque_types().num_entries() } + fn opaque_types_storage_num_unique_entries_raw(&self) -> usize { + self.inner.borrow_mut().opaque_types().num_entries().opaque_types + } fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { self.inner.borrow_mut().opaque_types().iter_lookup_table().map(|(k, h)| (k, h.ty)).collect() } diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 46752840e1bab..9879384ed3e20 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -20,7 +20,7 @@ pub struct OpaqueTypeStorage<'tcx> { /// the opaque types currently in the storage. #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] pub struct OpaqueTypeStorageEntries { - opaque_types: usize, + pub opaque_types: usize, duplicate_entries: usize, } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index c62f2e2e0e95f..ce05cd376de15 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -25,9 +25,9 @@ use crate::delegate::SolverDelegate; use crate::resolve::EagerResolver; use crate::solve::eval_ctxt::CurrentGoalKind; use crate::solve::{ - CanonicalInput, CanonicalResponse, Certainty, EvalCtxt, ExternalConstraintsData, Goal, - MaybeCause, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryInput, - QueryResult, Response, inspect, response_no_constraints_raw, + CanonicalGoalCacheKey, CanonicalInput, CanonicalResponse, Certainty, EvalCtxt, + ExternalConstraintsData, Goal, MaybeCause, NestedNormalizationGoals, NoSolution, + PredefinedOpaquesData, QueryInput, QueryResult, Response, inspect, response_no_constraints_raw, }; trait ResponseT { @@ -53,10 +53,26 @@ where { /// Canonicalizes the goal remembering the original values /// for each bound variable. - pub(super) fn canonicalize_goal>( + pub(super) fn canonicalize_goal( &self, - goal: Goal, - ) -> (Vec, CanonicalInput) { + goal: Goal, + cache_key: Option>, + ) -> (Vec, CanonicalInput) { + if let Some(cache_key) = cache_key { + if !cache_key.orig_values.iter().any(|value| self.delegate.is_changed_arg(value)) + && self.delegate.opaque_types_storage_num_unique_entries_raw() + == cache_key + .canonical_goal + .canonical + .value + .predefined_opaques_in_body + .opaque_types + .len() + { + return (cache_key.orig_values.to_vec(), cache_key.canonical_goal); + } + } + // We only care about one entry per `OpaqueTypeKey` here, // so we only canonicalize the lookup table and ignore // duplicate entries. @@ -130,7 +146,7 @@ where if goals.is_empty() { assert!(matches!(goals_certainty, Certainty::Yes)); } - (Certainty::Yes, NestedNormalizationGoals(goals)) + (Certainty::Yes, NestedNormalizationGoals::from(goals)) } _ => { let certainty = shallow_certainty.and(goals_certainty); 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 9a4b95903a970..00d91af8d13ca 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 @@ -22,8 +22,9 @@ use crate::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ - CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource, - HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, + CanonicalGoalCacheKey, CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, + GoalEvaluationKind, GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, + QueryResult, }; pub(super) mod canonical; @@ -115,7 +116,7 @@ where pub(super) search_graph: &'a mut SearchGraph, - nested_goals: Vec<(GoalSource, Goal)>, + nested_goals: Vec<(GoalSource, Goal, Option>)>, pub(super) origin_span: I::Span, @@ -147,8 +148,9 @@ pub trait SolverDelegateEvalExt: SolverDelegate { goal: Goal::Predicate>, generate_proof_tree: GenerateProofTree, span: ::Span, + cache_key: Option>, ) -> ( - Result<(HasChanged, Certainty), NoSolution>, + Result<(HasChanged, Certainty, CanonicalGoalCacheKey), NoSolution>, Option>, ); @@ -171,8 +173,17 @@ pub trait SolverDelegateEvalExt: SolverDelegate { &self, goal: Goal::Predicate>, generate_proof_tree: GenerateProofTree, + cache_key: Option>, ) -> ( - Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution>, + Result< + ( + NestedNormalizationGoals, + HasChanged, + Certainty, + CanonicalGoalCacheKey, + ), + NoSolution, + >, Option>, ); } @@ -188,9 +199,13 @@ where goal: Goal, generate_proof_tree: GenerateProofTree, span: I::Span, - ) -> (Result<(HasChanged, Certainty), NoSolution>, Option>) { + cache_key: Option>, + ) -> ( + Result<(HasChanged, Certainty, CanonicalGoalCacheKey), NoSolution>, + Option>, + ) { EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, span, |ecx| { - ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) + ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, cache_key) }) } @@ -201,7 +216,7 @@ where ) -> bool { self.probe(|| { EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, I::Span::dummy(), |ecx| { - ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) + ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, None) }) .0 }) @@ -213,8 +228,12 @@ where &self, goal: Goal, generate_proof_tree: GenerateProofTree, + cache_key: Option>, ) -> ( - Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution>, + Result< + (NestedNormalizationGoals, HasChanged, Certainty, CanonicalGoalCacheKey), + NoSolution, + >, Option>, ) { EvalCtxt::enter_root( @@ -222,7 +241,9 @@ where self.cx().recursion_limit(), generate_proof_tree, I::Span::dummy(), - |ecx| ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal), + |ecx| { + ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal, cache_key) + }, ) } } @@ -447,11 +468,12 @@ where goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, goal: Goal, - ) -> Result<(HasChanged, Certainty), NoSolution> { - let (normalization_nested_goals, has_changed, certainty) = - self.evaluate_goal_raw(goal_evaluation_kind, source, goal)?; + cache_key: Option>, + ) -> Result<(HasChanged, Certainty, CanonicalGoalCacheKey), NoSolution> { + let (normalization_nested_goals, has_changed, certainty, cache_key) = + self.evaluate_goal_raw(goal_evaluation_kind, source, goal, cache_key)?; assert!(normalization_nested_goals.is_empty()); - Ok((has_changed, certainty)) + Ok((has_changed, certainty, cache_key)) } /// Recursively evaluates `goal`, returning the nested goals in case @@ -466,8 +488,12 @@ where goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, goal: Goal, - ) -> Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution> { - let (orig_values, canonical_goal) = self.canonicalize_goal(goal); + cache_key: Option>, + ) -> Result< + (NestedNormalizationGoals, HasChanged, Certainty, CanonicalGoalCacheKey), + NoSolution, + > { + let (orig_values, canonical_goal) = self.canonicalize_goal(goal, cache_key); let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); let canonical_response = EvalCtxt::evaluate_canonical_goal( @@ -488,6 +514,7 @@ where let has_changed = if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No }; + let cache_orig_values = self.cx().mk_args(&orig_values); let (normalization_nested_goals, certainty) = self.instantiate_and_apply_query_response(goal.param_env, orig_values, response); self.inspect.goal_evaluation(goal_evaluation); @@ -502,7 +529,12 @@ where // Once we have decided on how to handle trait-system-refactor-initiative#75, // we should re-add an assert here. - Ok((normalization_nested_goals, has_changed, certainty)) + Ok(( + normalization_nested_goals, + has_changed, + certainty, + CanonicalGoalCacheKey { canonical_goal, orig_values: cache_orig_values }, + )) } fn compute_goal(&mut self, goal: Goal) -> QueryResult { @@ -602,7 +634,7 @@ where let cx = self.cx(); // If this loop did not result in any progress, what's our final certainty. let mut unchanged_certainty = Some(Certainty::Yes); - for (source, goal) in mem::take(&mut self.nested_goals) { + for (source, goal, cache_key) in mem::take(&mut self.nested_goals) { if let Some(has_changed) = self.delegate.compute_goal_fast_path(goal, self.origin_span) { if matches!(has_changed, HasChanged::Yes) { @@ -630,11 +662,16 @@ where let unconstrained_goal = goal.with(cx, ty::NormalizesTo { alias: pred.alias, term: unconstrained_rhs }); - let (NestedNormalizationGoals(nested_goals), _, certainty) = - self.evaluate_goal_raw(GoalEvaluationKind::Nested, source, unconstrained_goal)?; + let (NestedNormalizationGoals(nested_goals), _, certainty, _) = self + .evaluate_goal_raw( + GoalEvaluationKind::Nested, + source, + unconstrained_goal, + None, + )?; // Add the nested goals from normalization to our own nested goals. trace!(?nested_goals); - self.nested_goals.extend(nested_goals); + self.nested_goals.extend(nested_goals.into_iter().map(|(s, g)| (s, g, None))); // Finally, equate the goal's RHS with the unconstrained var. // @@ -668,13 +705,13 @@ where match certainty { Certainty::Yes => {} Certainty::Maybe(_) => { - self.nested_goals.push((source, with_resolved_vars)); + self.nested_goals.push((source, with_resolved_vars, None)); unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } } else { - let (has_changed, certainty) = - self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?; + let (has_changed, certainty, cache_key) = + self.evaluate_goal(GoalEvaluationKind::Nested, source, goal, cache_key)?; if has_changed == HasChanged::Yes { unchanged_certainty = None; } @@ -682,7 +719,7 @@ where match certainty { Certainty::Yes => {} Certainty::Maybe(_) => { - self.nested_goals.push((source, goal)); + self.nested_goals.push((source, goal, Some(cache_key))); unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } @@ -706,7 +743,7 @@ where goal.predicate = goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env)); self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal); - self.nested_goals.push((source, goal)); + self.nested_goals.push((source, goal, None)); } #[instrument(level = "trace", skip(self, goals))] diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index aa3be43fcd16b..03c94fe84d26f 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -13,8 +13,11 @@ use rustc_middle::ty::{ self, DelayedSet, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, TypingMode, }; use rustc_next_trait_solver::delegate::SolverDelegate as _; -use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _}; +use rustc_next_trait_solver::solve::{ + CanonicalGoalCacheKey, GenerateProofTree, HasChanged, SolverDelegateEvalExt as _, +}; use rustc_span::Span; +use thin_vec::ThinVec; use tracing::instrument; use self::derive_errors::*; @@ -25,6 +28,9 @@ use crate::traits::{FulfillmentError, ScrubbedTraitError}; mod derive_errors; +type PendingObligations<'tcx> = + ThinVec<(PredicateObligation<'tcx>, Option>>)>; + /// A trait engine using the new trait solver. /// /// This is mostly identical to how `evaluate_all` works inside of the @@ -54,13 +60,17 @@ struct ObligationStorage<'tcx> { /// We cannot eagerly return these as error so we instead store them here /// to avoid recomputing them each time `select_where_possible` is called. /// This also allows us to return the correct `FulfillmentError` for them. - overflowed: PredicateObligations<'tcx>, - pending: PredicateObligations<'tcx>, + overflowed: Vec>, + pending: PendingObligations<'tcx>, } impl<'tcx> ObligationStorage<'tcx> { - fn register(&mut self, obligation: PredicateObligation<'tcx>) { - self.pending.push(obligation); + fn register( + &mut self, + obligation: PredicateObligation<'tcx>, + cache_key: Option>>, + ) { + self.pending.push((obligation, cache_key)); } fn has_pending_obligations(&self) -> bool { @@ -68,7 +78,8 @@ impl<'tcx> ObligationStorage<'tcx> { } fn clone_pending(&self) -> PredicateObligations<'tcx> { - let mut obligations = self.pending.clone(); + let mut obligations: PredicateObligations<'tcx> = + self.pending.iter().map(|(o, _)| o.clone()).collect(); obligations.extend(self.overflowed.iter().cloned()); obligations } @@ -76,8 +87,9 @@ impl<'tcx> ObligationStorage<'tcx> { fn drain_pending( &mut self, cond: impl Fn(&PredicateObligation<'tcx>) -> bool, - ) -> PredicateObligations<'tcx> { - let (unstalled, pending) = mem::take(&mut self.pending).into_iter().partition(cond); + ) -> PendingObligations<'tcx> { + let (unstalled, pending) = + mem::take(&mut self.pending).into_iter().partition(|(o, _)| cond(o)); self.pending = pending; unstalled } @@ -90,13 +102,16 @@ impl<'tcx> ObligationStorage<'tcx> { // we were to do another step of `select_where_possible`, which goals would // change. // FIXME: is merged, this can be removed. - self.overflowed.extend(ExtractIf::new(&mut self.pending, |o| { - let goal = o.as_goal(); - let result = <&SolverDelegate<'tcx>>::from(infcx) - .evaluate_root_goal(goal, GenerateProofTree::No, o.cause.span) - .0; - matches!(result, Ok((HasChanged::Yes, _))) - })); + self.overflowed.extend( + ExtractIf::new(&mut self.pending, |(o, cache_key)| { + let goal = o.as_goal(); + let result = <&SolverDelegate<'tcx>>::from(infcx) + .evaluate_root_goal(goal, GenerateProofTree::No, o.cause.span, *cache_key) + .0; + matches!(result, Ok((HasChanged::Yes, _, _))) + }) + .map(|(o, _)| o), + ); }) } } @@ -119,11 +134,11 @@ impl<'tcx, E: 'tcx> FulfillmentCtxt<'tcx, E> { &self, infcx: &InferCtxt<'tcx>, obligation: &PredicateObligation<'tcx>, - result: &Result<(HasChanged, Certainty), NoSolution>, + result: &Result<(HasChanged, Certainty, CanonicalGoalCacheKey>), NoSolution>, ) { if let Some(inspector) = infcx.obligation_inspector.get() { let result = match result { - Ok((_, c)) => Ok(*c), + Ok((_, c, _)) => Ok(*c), Err(NoSolution) => Err(NoSolution), }; (inspector)(infcx, &obligation, result); @@ -142,14 +157,14 @@ where obligation: PredicateObligation<'tcx>, ) { assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots()); - self.obligations.register(obligation); + self.obligations.register(obligation, None); } fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { self.obligations .pending .drain(..) - .map(|obligation| NextSolverError::Ambiguity(obligation)) + .map(|(obligation, _)| NextSolverError::Ambiguity(obligation)) .chain( self.obligations .overflowed @@ -165,7 +180,7 @@ where let mut errors = Vec::new(); loop { let mut has_changed = false; - for mut obligation in self.obligations.drain_pending(|_| true) { + for (mut obligation, cache_key) in self.obligations.drain_pending(|_| true) { if !infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) { self.obligations.on_fulfillment_overflow(infcx); // Only return true errors that we have accumulated while processing. @@ -182,10 +197,15 @@ where } let result = delegate - .evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span) + .evaluate_root_goal( + goal, + GenerateProofTree::No, + obligation.cause.span, + cache_key, + ) .0; self.inspect_evaluated_obligation(infcx, &obligation, &result); - let (changed, certainty) = match result { + let (changed, certainty, cache_key) = match result { Ok(result) => result, Err(NoSolution) => { errors.push(E::from_solver_error( @@ -209,7 +229,7 @@ where match certainty { Certainty::Yes => {} - Certainty::Maybe(_) => self.obligations.register(obligation), + Certainty::Maybe(_) => self.obligations.register(obligation, Some(cache_key)), } } @@ -247,20 +267,24 @@ where return Default::default(); } - self.obligations.drain_pending(|obl| { - infcx.probe(|_| { - infcx - .visit_proof_tree( - obl.as_goal(), - &mut StalledOnCoroutines { - stalled_generators, - span: obl.cause.span, - cache: Default::default(), - }, - ) - .is_break() + self.obligations + .drain_pending(|obl| { + infcx.probe(|_| { + infcx + .visit_proof_tree( + obl.as_goal(), + &mut StalledOnCoroutines { + stalled_generators, + span: obl.cause.span, + cache: Default::default(), + }, + ) + .is_break() + }) }) - }) + .into_iter() + .map(|(o, _)| o) + .collect() } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index f64cd5ffebe3d..7954edb970369 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -93,10 +93,11 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>( root_obligation.as_goal(), GenerateProofTree::No, root_obligation.cause.span, + None, ) .0 { - Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { + Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => { (FulfillmentErrorCode::Ambiguity { overflow: None }, true) } Ok(( @@ -105,6 +106,7 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>( suggest_increasing_limit, keep_constraints: _, }), + _, )) => ( FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, // Don't look into overflows because we treat overflows weirdly anyways. @@ -115,7 +117,7 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>( // FIXME: We should probably just look into overflows here. false, ), - Ok((_, Certainty::Yes)) => { + Ok((_, Certainty::Yes, _)) => { bug!( "did not expect successful goal when collecting ambiguity errors for `{:?}`", infcx.resolve_vars_if_possible(root_obligation.predicate), diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 9795655e84222..49a8b363b0aba 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -219,8 +219,8 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { // building their proof tree, the expected term was unconstrained, but when // instantiating the candidate it is already constrained to the result of another // candidate. - let proof_tree = - infcx.probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes).1); + let proof_tree = infcx + .probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes, None).1); InspectGoal::new( infcx, self.goal.depth + 1, @@ -236,7 +236,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { // constraints, we get an ICE if we already applied the constraints // from the chosen candidate. let proof_tree = infcx - .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes, span).1) + .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes, span, None).1) .unwrap(); InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source) } @@ -442,6 +442,7 @@ impl<'tcx> InferCtxt<'tcx> { goal, GenerateProofTree::Yes, visitor.span(), + None, ); let proof_tree = proof_tree.unwrap(); visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None, GoalSource::Misc)) diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index c149076211739..0cb82e9dd6311 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -168,6 +168,8 @@ pub trait InferCtxtLike: Sized { vid: ty::RegionVid, ) -> ::Region; + fn is_changed_arg(&self, arg: ::GenericArg) -> bool; + fn next_region_infer(&self) -> ::Region; fn next_ty_infer(&self) -> ::Ty; fn next_const_infer(&self) -> ::Const; @@ -250,6 +252,7 @@ pub trait InferCtxtLike: Sized { type OpaqueTypeStorageEntries: Debug + Copy + Default; fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries; + fn opaque_types_storage_num_unique_entries_raw(&self) -> usize; fn clone_opaque_types_lookup_table( &self, ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 2e05c23a6458c..e97053b83f6eb 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -251,6 +251,16 @@ impl NestedNormalizationGoals { } } +impl From, Option>)>> + for NestedNormalizationGoals +{ + fn from( + value: Vec<(GoalSource, Goal, Option>)>, + ) -> Self { + NestedNormalizationGoals(value.into_iter().map(|(s, g, _)| (s, g)).collect()) + } +} + #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub enum Certainty { @@ -358,3 +368,11 @@ pub enum AdtDestructorKind { NotConst, Const, } + +#[derive_where(Copy, Clone, Hash, PartialEq, Eq, Debug; I: Interner)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +pub struct CanonicalGoalCacheKey { + pub canonical_goal: CanonicalInput, + pub orig_values: I::GenericArgs, +}