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 1ab7ac4c2e361..a2d016a57383c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -39,6 +39,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.type_matches_expected_vid(expected_vid, data.self_ty()) } ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { + if !matches!( + data.projection_term.kind(self.tcx), + ty::AliasTermKind::ProjectionTy + | ty::AliasTermKind::ProjectionConst + | ty::AliasTermKind::InherentTy + | ty::AliasTermKind::InherentConst + ) { + return false; + } + self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty()) } ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 1f64f09fe787f..e878785362211 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -97,13 +97,19 @@ pub(super) fn instantiate_and_apply_query_response( original_values: &[I::GenericArg], response: CanonicalResponse, span: I::Span, + prev_universe: ty::UniverseIndex, ) -> (NestedNormalizationGoals, Certainty) where D: SolverDelegate, I: Interner, { - let instantiation = - compute_query_response_instantiation_values(delegate, &original_values, &response, span); + let instantiation = compute_query_response_instantiation_values( + delegate, + &original_values, + &response, + span, + prev_universe, + ); let Response { var_values, external_constraints, certainty } = delegate.instantiate_canonical(response, instantiation); @@ -127,6 +133,7 @@ fn compute_query_response_instantiation_values( original_values: &[I::GenericArg], response: &Canonical, span: I::Span, + prev_universe: ty::UniverseIndex, ) -> CanonicalVarValues where D: SolverDelegate, @@ -136,7 +143,6 @@ where // FIXME: Longterm canonical queries should deal with all placeholders // created inside of the query directly instead of returning them to the // caller. - let prev_universe = delegate.universe(); let universes_created_in_query = response.max_universe.index(); for _ in 0..universes_created_in_query { delegate.create_next_universe(); @@ -328,8 +334,13 @@ where .map(|&arg| delegate.fresh_var_for_kind_with_span(arg, span)), ); - let instantiation = - compute_query_response_instantiation_values(delegate, orig_values, &state, span); + let instantiation = compute_query_response_instantiation_values( + delegate, + orig_values, + &state, + span, + delegate.universe(), + ); let inspect::State { var_values, data } = delegate.instantiate_canonical(state, instantiation); diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs index f7bd460094328..2353e495dcc5b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs +++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs @@ -52,7 +52,13 @@ where let term = self.next_term_infer_of_kind(lhs); self.add_goal( GoalSource::TypeRelating, - goal.with(cx, ty::NormalizesTo { alias, term }), + goal.with( + cx, + ty::ClauseKind::Projection(ty::ProjectionPredicate { + projection_term: alias, + term, + }), + ), ); term } else { @@ -64,7 +70,13 @@ where let term = self.next_term_infer_of_kind(rhs); self.add_goal( GoalSource::TypeRelating, - goal.with(cx, ty::NormalizesTo { alias, term }), + goal.with( + cx, + ty::ClauseKind::Projection(ty::ProjectionPredicate { + projection_term: alias, + term, + }), + ), ); term } else { 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 6841fe1c5124e..9597b2de763c1 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 @@ -40,7 +40,7 @@ mod probe; /// This has effects on cycle handling handling and on how we compute /// query responses, see the variant descriptions for more info. #[derive(Debug, Copy, Clone)] -enum CurrentGoalKind { +pub(super) enum CurrentGoalKind { Misc, /// We're proving an trait goal for a coinductive trait, either an auto trait or `Sized`. /// @@ -93,15 +93,15 @@ where /// If some `InferCtxt` method is missing, please first think defensively about /// the method's compatibility with this solver, or if an existing one does /// the job already. - delegate: &'a D, + pub(super) delegate: &'a D, /// The variable info for the `var_values`, only used to make an ambiguous response /// with no constraints. - var_kinds: I::CanonicalVarKinds, + pub(super) var_kinds: I::CanonicalVarKinds, /// What kind of goal we're currently computing, see the enum definition /// for more info. - current_goal_kind: CurrentGoalKind, + pub(super) current_goal_kind: CurrentGoalKind, pub(super) var_values: CanonicalVarValues, /// The highest universe index nameable by the caller. @@ -486,6 +486,7 @@ where &orig_values, response, self.origin_span, + self.delegate.universe(), ); // FIXME: We previously had an assert here that checked that recomputing @@ -564,7 +565,7 @@ where pub(super) fn compute_goal(&mut self, goal: Goal) -> QueryResult { let Goal { param_env, predicate } = goal; let kind = predicate.kind(); - self.enter_forall(kind, |ecx, kind| match kind { + let resp = self.enter_forall(kind, |ecx, kind| match kind { ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => { ecx.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r) } @@ -604,8 +605,8 @@ where ty::PredicateKind::ConstEquate(_, _) => { panic!("ConstEquate should not be emitted when `-Znext-solver` is active") } - ty::PredicateKind::NormalizesTo(predicate) => { - ecx.compute_normalizes_to_goal(Goal { param_env, predicate }) + ty::PredicateKind::NormalizesTo(_) => { + unreachable!() } ty::PredicateKind::AliasRelate(lhs, rhs, direction) => { ecx.compute_alias_relate_goal(Goal { param_env, predicate: (lhs, rhs, direction) }) @@ -613,7 +614,9 @@ where ty::PredicateKind::Ambiguous => { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } - }) + })?; + debug_assert!(resp.value.external_constraints.normalization_nested_goals.is_empty()); + Ok(resp) } // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning @@ -806,6 +809,7 @@ where /// /// This is the case if the `term` does not occur in any other part of the predicate /// and is able to name all other placeholder and inference variables. + #[allow(unused)] #[instrument(level = "trace", skip(self), ret)] pub(super) fn term_is_fully_unconstrained(&self, goal: Goal>) -> bool { let universe_of_term = match goal.predicate.term.kind() { @@ -832,6 +836,7 @@ where cache: HashSet, } + #[allow(unused)] impl, I: Interner> ContainsTermOrNotNameable<'_, D, I> { fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> { if self.universe_of_term.can_name(universe) { @@ -1423,16 +1428,15 @@ where fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { match ty.kind() { - ty::Alias(..) if !ty.has_escaping_bound_vars() => { + ty::Alias(_, alias) if !ty.has_escaping_bound_vars() => { let infer_ty = self.ecx.next_ty_infer(); - let normalizes_to = ty::PredicateKind::AliasRelate( - ty.into(), - infer_ty.into(), - ty::AliasRelationDirection::Equate, - ); + let projection = ty::ClauseKind::Projection(ty::ProjectionPredicate { + projection_term: alias.into(), + term: infer_ty.into(), + }); self.ecx.add_goal( self.normalization_goal_source, - Goal::new(self.cx(), self.param_env, normalizes_to), + Goal::new(self.cx(), self.param_env, projection), ); infer_ty } @@ -1452,16 +1456,15 @@ where fn fold_const(&mut self, ct: I::Const) -> I::Const { match ct.kind() { - ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => { + ty::ConstKind::Unevaluated(uc) if !ct.has_escaping_bound_vars() => { let infer_ct = self.ecx.next_const_infer(); - let normalizes_to = ty::PredicateKind::AliasRelate( - ct.into(), - infer_ct.into(), - ty::AliasRelationDirection::Equate, - ); + let projection = ty::ClauseKind::Projection(ty::ProjectionPredicate { + projection_term: uc.into(), + term: infer_ct.into(), + }); self.ecx.add_goal( self.normalization_goal_source, - Goal::new(self.cx(), self.param_env, normalizes_to), + Goal::new(self.cx(), self.param_env, projection), ); infer_ct } @@ -1528,6 +1531,7 @@ pub(super) fn evaluate_root_goal_for_proof_tree, &proof_tree.orig_values, response, origin_span, + delegate.universe(), ); (Ok(normalization_nested_goals), proof_tree) diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 58bd7cf663d98..5213b983cfdb2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -16,7 +16,6 @@ mod assembly; mod effect_goals; mod eval_ctxt; pub mod inspect; -mod normalizes_to; mod project_goals; mod search_graph; mod trait_goals; diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs deleted file mode 100644 index 944d5f0e042d7..0000000000000 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs +++ /dev/null @@ -1,31 +0,0 @@ -use rustc_type_ir::{self as ty, Interner, ProjectionPredicate}; -use tracing::instrument; - -use crate::delegate::SolverDelegate; -use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult}; - -impl EvalCtxt<'_, D> -where - D: SolverDelegate, - I: Interner, -{ - #[instrument(level = "trace", skip(self), ret)] - pub(super) fn compute_projection_goal( - &mut self, - goal: Goal>, - ) -> QueryResult { - let cx = self.cx(); - let projection_term = goal.predicate.projection_term.to_term(cx); - let goal = goal.with( - cx, - ty::PredicateKind::AliasRelate( - projection_term, - goal.predicate.term, - ty::AliasRelationDirection::Equate, - ), - ); - // A projection goal holds if the alias is equal to the expected term. - self.add_goal(GoalSource::TypeRelating, goal); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } -} diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/anon_const.rs similarity index 78% rename from compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs rename to compiler/rustc_next_trait_solver/src/solve/project_goals/anon_const.rs index eb6a1b51421ca..a1271acaa7bd8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/anon_const.rs @@ -12,10 +12,11 @@ where #[instrument(level = "trace", skip(self), ret)] pub(super) fn normalize_anon_const( &mut self, - goal: Goal>, + goal: Goal>, ) -> QueryResult { if self.typing_mode() == TypingMode::Coherence - && self.cx().anon_const_kind(goal.predicate.alias.def_id) == ty::AnonConstKind::OGCA + && self.cx().anon_const_kind(goal.predicate.projection_term.def_id) + == ty::AnonConstKind::OGCA { // During coherence, OGCA consts should be normalized ambiguously // because they are opaque but eventually resolved to a real value. @@ -28,11 +29,11 @@ where } else if let Some(normalized_const) = self.evaluate_const( goal.param_env, ty::UnevaluatedConst::new( - goal.predicate.alias.def_id.try_into().unwrap(), - goal.predicate.alias.args, + goal.predicate.projection_term.def_id.try_into().unwrap(), + goal.predicate.projection_term.args, ), ) { - self.instantiate_normalizes_to_term(goal, normalized_const.into()); + self.instantiate_projection_term(goal, normalized_const.into())?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs similarity index 88% rename from compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs rename to compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs index 8777f84957a79..852d3ec7532fd 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs @@ -16,10 +16,10 @@ where { pub(super) fn normalize_free_alias( &mut self, - goal: Goal>, + goal: Goal>, ) -> QueryResult { let cx = self.cx(); - let free_alias = goal.predicate.alias; + let free_alias = goal.predicate.projection_term; // Check where clauses self.add_goals( @@ -35,7 +35,7 @@ where cx.const_of_item(free_alias.def_id).instantiate(cx, free_alias.args).into() }; - self.instantiate_normalizes_to_term(goal, actual); + self.instantiate_projection_term(goal, actual)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs similarity index 93% rename from compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs rename to compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs index 42aa237762d9e..ee63c2cae0b2d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs @@ -17,10 +17,10 @@ where { pub(super) fn normalize_inherent_associated_term( &mut self, - goal: Goal>, + goal: Goal>, ) -> QueryResult { let cx = self.cx(); - let inherent = goal.predicate.alias; + let inherent = goal.predicate.projection_term; let impl_def_id = cx.parent(inherent.def_id); let impl_args = self.fresh_args_for_item(impl_def_id); @@ -56,7 +56,7 @@ where } else { cx.const_of_item(inherent.def_id).instantiate(cx, inherent_args).into() }; - self.instantiate_normalizes_to_term(goal, normalized); + self.instantiate_projection_term(goal, normalized)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs similarity index 81% rename from compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs rename to compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs index 13f2ad8f82eba..66781bbddbd38 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs @@ -7,12 +7,14 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::SizedTraitKind; -use rustc_type_ir::{self as ty, FieldInfo, Interner, NormalizesTo, PredicateKind, Upcast as _}; +use rustc_type_ir::{self as ty, FieldInfo, Interner, PredicateKind, Upcast as _}; use tracing::instrument; +use crate::canonical::instantiate_and_apply_query_response; use crate::delegate::SolverDelegate; use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes}; use crate::solve::assembly::{self, Candidate}; +use crate::solve::eval_ctxt::CurrentGoalKind; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, @@ -25,63 +27,120 @@ where I: Interner, { #[instrument(level = "trace", skip(self), ret)] - pub(super) fn compute_normalizes_to_goal( + pub(super) fn compute_projection_goal( &mut self, - goal: Goal>, + goal: Goal>, ) -> QueryResult { - debug_assert!(self.term_is_fully_unconstrained(goal)); let cx = self.cx(); - match goal.predicate.alias.kind(cx) { + match goal.predicate.projection_term.kind(cx) { ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => { - let trait_ref = goal.predicate.alias.trait_ref(cx); + let trait_ref = goal.predicate.projection_term.trait_ref(cx); let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| { let trait_goal: Goal> = goal.with(cx, trait_ref); ecx.compute_trait_goal(trait_goal) })?; - self.assemble_and_merge_candidates( - proven_via, - goal, - |ecx| { - // FIXME(generic_associated_types): Addresses aggressive inference in #92917. - // - // If this type is a GAT with currently unconstrained arguments, we do not - // want to normalize it via a candidate which only applies for a specific - // instantiation. We could otherwise keep the GAT as rigid and succeed this way. - // See tests/ui/generic-associated-types/no-incomplete-gat-arg-inference.rs. - // - // This only avoids normalization if a GAT argument is fully unconstrained. - // This is quite arbitrary but fixing it causes some ambiguity, see #125196. - for arg in goal.predicate.alias.own_args(cx).iter() { - let Some(term) = arg.as_term() else { - continue; - }; - match ecx.structurally_normalize_term(goal.param_env, term) { - Ok(term) => { - if term.is_infer() { - return Some( + + let term = self.next_term_infer_of_kind(goal.predicate.term); + self.eq(goal.param_env, goal.predicate.term, term)?; + let unconstrained_term = self.next_term_infer_of_kind(goal.predicate.term); + let unconstrained_goal: Goal> = Goal { + param_env: goal.param_env, + predicate: ty::ProjectionPredicate { + projection_term: goal.predicate.projection_term, + term: unconstrained_term, + }, + }; + + let extended_var_values = cx.mk_args_from_iter( + self.var_values + .var_values + .iter() + .chain(std::iter::once(unconstrained_term.into())), + ); + let mut extended_var_kinds = self.var_kinds.to_vec(); + let extra_var_kind = match unconstrained_term.kind() { + ty::TermKind::Ty(_) => ty::CanonicalVarKind::Ty { + ui: self.max_input_universe, + sub_root: ty::BoundVar::from_usize(extended_var_kinds.len()), + }, + ty::TermKind::Const(_) => ty::CanonicalVarKind::Const(self.max_input_universe), + }; + extended_var_kinds.push(extra_var_kind); + let extended_var_kinds = cx.mk_canonical_var_kinds(&extended_var_kinds); + + let resp = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| { + ecx.var_values.var_values = extended_var_values; + ecx.var_kinds = extended_var_kinds; + ecx.current_goal_kind = CurrentGoalKind::NormalizesTo; + + ecx.assemble_and_merge_candidates( + proven_via, + unconstrained_goal, + |ecx| { + // FIXME(generic_associated_types): Addresses aggressive inference in #92917. + // + // If this type is a GAT with currently unconstrained arguments, we do not + // want to normalize it via a candidate which only applies for a specific + // instantiation. We could otherwise keep the GAT as rigid and succeed this way. + // See tests/ui/generic-associated-types/no-incomplete-gat-arg-inference.rs. + // + // This only avoids normalization if a GAT argument is fully unconstrained. + // This is quite arbitrary but fixing it causes some ambiguity, see #125196. + for arg in + unconstrained_goal.predicate.projection_term.own_args(cx).iter() + { + let Some(term) = arg.as_term() else { + continue; + }; + match ecx + .structurally_normalize_term(unconstrained_goal.param_env, term) + { + Ok(term) => { + if term.is_infer() { + return Some( ecx.evaluate_added_goals_and_make_canonical_response( Certainty::AMBIGUOUS, ), ); + } } + Err(NoSolution) => return Some(Err(NoSolution)), } - Err(NoSolution) => return Some(Err(NoSolution)), } - } - None - }, - |ecx| { - ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| { - this.structurally_instantiate_normalizes_to_term( - goal, - goal.predicate.alias, - ); - this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) - }, - ) + None + }, + |ecx| { + ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| { + this.structurally_instantiate_projection_term( + unconstrained_goal, + unconstrained_goal.predicate.projection_term, + )?; + this.evaluate_added_goals_and_make_canonical_response( + Certainty::Yes, + ) + }) + }, + ) + })?; + + let (nested_goals, certainty) = instantiate_and_apply_query_response( + self.delegate, + goal.param_env, + extended_var_values.as_slice(), + resp, + self.origin_span, + self.max_input_universe, + ); + + self.eq_structurally_relating_aliases(goal.param_env, term, unconstrained_term)?; + + for (source, nested_goal) in nested_goals.0 { + self.add_goal(source, nested_goal); + } + + self.evaluate_added_goals_and_make_canonical_response(certainty) } ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst => { self.normalize_inherent_associated_term(goal) @@ -99,28 +158,26 @@ where /// We know `term` to always be a fully unconstrained inference variable, so /// `eq` should never fail here. However, in case `term` contains aliases, we /// emit nested `AliasRelate` goals to structurally normalize the alias. - pub fn instantiate_normalizes_to_term( + pub fn instantiate_projection_term( &mut self, - goal: Goal>, + goal: Goal>, term: I::Term, - ) { + ) -> Result<(), NoSolution> { self.eq(goal.param_env, goal.predicate.term, term) - .expect("expected goal term to be fully unconstrained"); } - /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term + /// Unlike `instantiate_projection_term` this instantiates the expected term /// with a rigid alias. Using this is pretty much always wrong. - pub fn structurally_instantiate_normalizes_to_term( + pub fn structurally_instantiate_projection_term( &mut self, - goal: Goal>, + goal: Goal>, term: ty::AliasTerm, - ) { + ) -> Result<(), NoSolution> { self.relate_rigid_alias_non_alias(goal.param_env, term, ty::Invariant, goal.predicate.term) - .expect("expected goal term to be fully unconstrained"); } } -impl assembly::GoalKind for NormalizesTo +impl assembly::GoalKind for ty::ProjectionPredicate where D: SolverDelegate, I: Interner, @@ -130,7 +187,7 @@ where } fn trait_ref(self, cx: I) -> ty::TraitRef { - self.alias.trait_ref(cx) + self.projection_term.trait_ref(cx) } fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { @@ -149,7 +206,7 @@ where if let Some(projection_pred) = assumption.as_projection_clause() && projection_pred.item_def_id() == goal.predicate.def_id() && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( - goal.predicate.alias.args, + goal.predicate.projection_term.args, projection_pred.skip_binder().projection_term.args, ) { @@ -168,16 +225,20 @@ where let cx = ecx.cx(); let projection_pred = assumption.as_projection_clause().unwrap(); let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); - ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?; + ecx.eq( + goal.param_env, + goal.predicate.projection_term, + assumption_projection_pred.projection_term, + )?; - ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); + ecx.instantiate_projection_term(goal, assumption_projection_pred.term)?; // Add GAT where clauses from the trait's definition // FIXME: We don't need these, since these are the type's own WF obligations. ecx.add_goals( GoalSource::AliasWellFormed, cx.own_predicates_of(goal.predicate.def_id()) - .iter_instantiated(cx, goal.predicate.alias.args) + .iter_instantiated(cx, goal.predicate.projection_term.args) .map(|pred| goal.with(cx, pred)), ); @@ -208,16 +269,16 @@ where fn consider_impl_candidate( ecx: &mut EvalCtxt<'_, D>, - goal: Goal>, + goal: Goal>, impl_def_id: I::ImplId, then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult, ) -> Result, NoSolution> { let cx = ecx.cx(); - let goal_trait_ref = goal.predicate.alias.trait_ref(cx); + let goal_trait_ref = goal.predicate.projection_term.trait_ref(cx); let impl_trait_ref = cx.impl_trait_ref(impl_def_id); if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify( - goal.predicate.alias.trait_ref(cx).args, + goal.predicate.projection_term.trait_ref(cx).args, impl_trait_ref.skip_binder().args, ) { return Err(NoSolution); @@ -257,17 +318,17 @@ where ecx.add_goals( GoalSource::AliasWellFormed, cx.own_predicates_of(goal.predicate.def_id()) - .iter_instantiated(cx, goal.predicate.alias.args) + .iter_instantiated(cx, goal.predicate.projection_term.args) .map(|pred| goal.with(cx, pred)), ); let error_response = |ecx: &mut EvalCtxt<'_, D>, guar| { - let error_term = match goal.predicate.alias.kind(cx) { + let error_term = match goal.predicate.projection_term.kind(cx) { ty::AliasTermKind::ProjectionTy => Ty::new_error(cx, guar).into(), ty::AliasTermKind::ProjectionConst => Const::new_error(cx, guar).into(), kind => panic!("expected projection, found {kind:?}"), }; - ecx.instantiate_normalizes_to_term(goal, error_term); + ecx.instantiate_projection_term(goal, error_term)?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }; @@ -300,10 +361,10 @@ where | ty::TypingMode::Borrowck { .. } | ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis => { - ecx.structurally_instantiate_normalizes_to_term( + ecx.structurally_instantiate_projection_term( goal, - goal.predicate.alias, - ); + goal.predicate.projection_term, + )?; return ecx .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); } @@ -338,10 +399,10 @@ where | ty::TypingMode::Borrowck { .. } | ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis => { - ecx.structurally_instantiate_normalizes_to_term( + ecx.structurally_instantiate_projection_term( goal, - goal.predicate.alias, - ); + goal.predicate.projection_term, + )?; return then(ecx, Certainty::Yes); } } @@ -378,7 +439,7 @@ where } // Finally we construct the actual value of the associated type. - let term = match goal.predicate.alias.kind(cx) { + let term = match goal.predicate.projection_term.kind(cx) { ty::AliasTermKind::ProjectionTy => { cx.type_of(target_item_def_id).map_bound(|ty| ty.into()) } @@ -388,7 +449,7 @@ where kind => panic!("expected projection, found {kind:?}"), }; - ecx.instantiate_normalizes_to_term(goal, term.instantiate(cx, target_args)); + ecx.instantiate_projection_term(goal, term.instantiate(cx, target_args))?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -488,7 +549,9 @@ where let cx = ecx.cx(); let env_region = match goal_kind { - ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2), + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { + goal.predicate.projection_term.args.region_at(2) + } // Doesn't matter what this region is ty::ClosureKind::FnOnce => Region::new_static(cx), }; @@ -573,7 +636,7 @@ where tupled_inputs_ty, tupled_upvars_ty, coroutine_captures_by_ref_ty, - ] = *goal.predicate.alias.args.as_slice() + ] = *goal.predicate.projection_term.args.as_slice() else { panic!(); }; @@ -604,7 +667,7 @@ where ); ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.instantiate_normalizes_to_term(goal, upvars_ty.into()); + ecx.instantiate_projection_term(goal, upvars_ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -666,17 +729,17 @@ where [I::GenericArg::from(goal.predicate.self_ty())], ); ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate)); - ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into()); + ecx.instantiate_projection_term(goal, Ty::new_unit(cx).into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }); // In case the dummy alias-bound candidate does not apply, we instead treat this projection // as rigid. return alias_bound_result.or_else(|NoSolution| { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| { - this.structurally_instantiate_normalizes_to_term( + this.structurally_instantiate_projection_term( goal, - goal.predicate.alias, - ); + goal.predicate.projection_term, + )?; this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) }); @@ -708,7 +771,7 @@ where }; ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.instantiate_normalizes_to_term(goal, metadata_ty.into()); + ecx.instantiate_projection_term(goal, metadata_ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -815,7 +878,7 @@ where ); let yield_ty = args.as_coroutine().yield_ty(); ecx.eq(goal.param_env, wrapped_expected_ty, yield_ty)?; - ecx.instantiate_normalizes_to_term(goal, expected_ty.into()); + ecx.instantiate_projection_term(goal, expected_ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -912,7 +975,10 @@ where // this impl candidate anyways. It's still a bit scuffed. ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => { return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + ecx.structurally_instantiate_projection_term( + goal, + goal.predicate.projection_term, + )?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }); } @@ -925,7 +991,7 @@ where }; ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into()); + ecx.instantiate_projection_term(goal, discriminant_ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -969,7 +1035,7 @@ where _ => panic!("unexpected associated type {:?} in `Field`", goal.predicate), }; ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.instantiate_normalizes_to_term(goal, ty.into()); + ecx.instantiate_projection_term(goal, ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -982,7 +1048,7 @@ where { fn translate_args( &mut self, - goal: Goal>, + goal: Goal>, impl_def_id: I::ImplId, impl_args: I::GenericArgs, impl_trait_ref: rustc_type_ir::TraitRef, @@ -991,11 +1057,15 @@ where let cx = self.cx(); Ok(if target_container_def_id == impl_trait_ref.def_id.into() { // Default value from the trait definition. No need to rebase. - goal.predicate.alias.args + goal.predicate.projection_term.args } else if target_container_def_id == impl_def_id.into() { // Same impl, no need to fully translate, just a rebase from // the trait is sufficient. - goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), impl_args) + goal.predicate.projection_term.args.rebase_onto( + cx, + impl_trait_ref.def_id.into(), + impl_args, + ) } else { let target_args = self.fresh_args_for_item(target_container_def_id); let target_trait_ref = cx @@ -1011,7 +1081,11 @@ where .iter_instantiated(cx, target_args) .map(|pred| goal.with(cx, pred)), ); - goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), target_args) + goal.predicate.projection_term.args.rebase_onto( + cx, + impl_trait_ref.def_id.into(), + target_args, + ) }) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs similarity index 93% rename from compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs rename to compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs index a5f857a1dd85b..f391a36cbf861 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs @@ -15,10 +15,10 @@ where { pub(super) fn normalize_opaque_type( &mut self, - goal: Goal>, + goal: Goal>, ) -> QueryResult { let cx = self.cx(); - let opaque_ty = goal.predicate.alias; + let opaque_ty = goal.predicate.projection_term; let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const"); match self.typing_mode() { @@ -48,7 +48,10 @@ where .filter(|&def_id| defining_opaque_types.contains(&def_id)) else { // If we're not in the defining scope, treat the alias as rigid. - self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + self.structurally_instantiate_projection_term( + goal, + goal.predicate.projection_term, + )?; return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); }; @@ -111,7 +114,10 @@ where .as_local() .filter(|&def_id| defined_opaque_types.contains(&def_id)) else { - self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + self.structurally_instantiate_projection_term( + goal, + goal.predicate.projection_term, + )?; return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); }; diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 567f660a59383..a4428dba97e51 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -120,11 +120,10 @@ where tcx, self.at.cause.clone(), self.at.param_env, - ty::PredicateKind::AliasRelate( - alias_term.into(), - infer_term.into(), - ty::AliasRelationDirection::Equate, - ), + ty::ClauseKind::Projection(ty::ProjectionPredicate { + projection_term: alias_term.to_alias_term().unwrap(), + term: infer_term, + }), ); self.fulfill_cx.register_predicate_obligation(infcx, obligation); diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index ebeab8eddc6f5..ae0a157ab05f1 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -35,9 +35,9 @@ impl<'tcx> At<'_, 'tcx> { assert!(!term.is_infer(), "should have resolved vars before calling"); if self.infcx.next_trait_solver() { - if let None = term.to_alias_term() { + let Some(alias) = term.to_alias_term() else { return Ok(term); - } + }; let new_infer = self.infcx.next_term_var_of_kind(term, self.cause.span); @@ -48,7 +48,10 @@ impl<'tcx> At<'_, 'tcx> { self.infcx.tcx, self.cause.clone(), self.param_env, - ty::PredicateKind::AliasRelate(term, new_infer, ty::AliasRelationDirection::Equate), + ty::ClauseKind::Projection(ty::ProjectionPredicate { + projection_term: alias, + term: new_infer, + }), ); fulfill_cx.register_predicate_obligation(self.infcx, obligation);