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 d6ed220909732..22bc550116bb9 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 @@ -1,5 +1,4 @@ use std::mem; -use std::ops::ControlFlow; #[cfg(feature = "nightly")] use rustc_macros::HashStable_NoContext; @@ -11,8 +10,7 @@ use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind}; use rustc_type_ir::solve::OpaqueTypesJank; use rustc_type_ir::{ self as ty, CanonicalVarValues, InferCtxtLike, Interner, Ty, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, - TypingMode, + TypeSuperFoldable, TypeVisitableExt, TypingMode, }; use tracing::{debug, instrument, trace}; @@ -47,13 +45,13 @@ enum CurrentGoalKind { /// These are currently the only goals whose impl where-clauses are considered to be /// productive steps. CoinductiveTrait, - /// Unlike other goals, `NormalizesTo` goals act like functions with the expected term - /// always being fully unconstrained. This would weaken inference however, as the nested + /// When probing and selecting `NormalizesTo` goal's projection candidates, the expected + /// term is always fully unconstrained. This would weaken inference however, as the nested /// goals never get the inference constraints from the actual normalized-to type. /// - /// Because of this we return any ambiguous nested goals from `NormalizesTo` to the - /// caller when then adds these to its own context. The caller is always an `AliasRelate` - /// goal so this never leaks out of the solver. + /// Because of this we return any ambiguous nested goals from the candidate probe to the + /// root of the `NormalizesTo` goal then adds these to its own context. So this never leaks + /// out of the solver. NormalizesTo, } @@ -67,7 +65,6 @@ impl CurrentGoalKind { CurrentGoalKind::Misc } } - ty::PredicateKind::NormalizesTo(_) => CurrentGoalKind::NormalizesTo, _ => CurrentGoalKind::Misc, } } @@ -509,17 +506,6 @@ where HasChanged::No => { let mut stalled_vars = orig_values; - // Remove the unconstrained RHS arg, which is expected to have changed. - if let Some(normalizes_to) = goal.predicate.as_normalizes_to() { - let normalizes_to = normalizes_to.skip_binder(); - let rhs_arg: I::GenericArg = normalizes_to.term.into(); - let idx = stalled_vars - .iter() - .rposition(|arg| *arg == rhs_arg) - .expect("expected unconstrained arg"); - stalled_vars.swap_remove(idx); - } - // Remove the canonicalized universal vars, since we only care about stalled existentials. let mut sub_roots = Vec::new(); stalled_vars.retain(|arg| match arg.kind() { @@ -564,7 +550,12 @@ 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 { + + if let Some(normalizes_to) = predicate.as_normalizes_to() { + assert!(!normalizes_to.skip_binder().has_escaping_bound_vars()); + } + + 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) } @@ -613,7 +604,11 @@ where ty::PredicateKind::Ambiguous => { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } - }) + })?; + + assert!(resp.value.external_constraints.normalization_nested_goals.is_empty()); + + Ok(resp) } // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning @@ -639,7 +634,6 @@ where /// /// Goals for the next step get directly added to the nested goals of the `EvalCtxt`. fn evaluate_added_goals_step(&mut self) -> Result, NoSolution> { - 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, stalled_on) in mem::take(&mut self.nested_goals) { @@ -654,92 +648,17 @@ where continue; } - // We treat normalizes-to goals specially here. In each iteration we take the - // RHS of the projection, replace it with a fresh inference variable, and only - // after evaluating that goal do we equate the fresh inference variable with the - // actual RHS of the predicate. - // - // This is both to improve caching, and to avoid using the RHS of the - // projection predicate to influence the normalizes-to candidate we select. - // - // Forgetting to replace the RHS with a fresh inference variable when we evaluate - // this goal results in an ICE. - if let Some(pred) = goal.predicate.as_normalizes_to() { - // We should never encounter higher-ranked normalizes-to goals. - let pred = pred.no_bound_vars().unwrap(); - // Replace the goal with an unconstrained infer var, so the - // RHS does not affect projection candidate assembly. - let unconstrained_rhs = self.next_term_infer_of_kind(pred.term); - let unconstrained_goal = - goal.with(cx, ty::NormalizesTo { alias: pred.alias, term: unconstrained_rhs }); - - let ( - NestedNormalizationGoals(nested_goals), - GoalEvaluation { goal, certainty, stalled_on, has_changed: _ }, - ) = self.evaluate_goal_raw(source, unconstrained_goal, stalled_on)?; - // Add the nested goals from normalization to our own nested goals. - trace!(?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. - // - // SUBTLE: - // We structurally relate aliases here. This is necessary - // as we otherwise emit a nested `AliasRelate` goal in case the - // returned term is a rigid alias, resulting in overflow. - // - // It is correct as both `goal.predicate.term` and `unconstrained_rhs` - // start out as an unconstrained inference variable so any aliases get - // fully normalized when instantiating it. - // - // FIXME: Strictly speaking this may be incomplete if the normalized-to - // type contains an ambiguous alias referencing bound regions. We should - // consider changing this to only use "shallow structural equality". - self.eq_structurally_relating_aliases( - goal.param_env, - pred.term, - unconstrained_rhs, - )?; - - // We only look at the `projection_ty` part here rather than - // looking at the "has changed" return from evaluate_goal, - // because we expect the `unconstrained_rhs` part of the predicate - // to have changed -- that means we actually normalized successfully! - // FIXME: Do we need to eagerly resolve here? Or should we check - // if the cache key has any changed vars? - let with_resolved_vars = self.resolve_vars_if_possible(goal); - if pred.alias - != with_resolved_vars - .predicate - .as_normalizes_to() - .unwrap() - .no_bound_vars() - .unwrap() - .alias - { - unchanged_certainty = None; - } - - match certainty { - Certainty::Yes => {} - Certainty::Maybe { .. } => { - self.nested_goals.push((source, with_resolved_vars, stalled_on)); - unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); - } - } - } else { - let GoalEvaluation { goal, certainty, has_changed, stalled_on } = - self.evaluate_goal(source, goal, stalled_on)?; - if has_changed == HasChanged::Yes { - unchanged_certainty = None; - } + let GoalEvaluation { goal, certainty, has_changed, stalled_on } = + self.evaluate_goal(source, goal, stalled_on)?; + if has_changed == HasChanged::Yes { + unchanged_certainty = None; + } - match certainty { - Certainty::Yes => {} - Certainty::Maybe { .. } => { - self.nested_goals.push((source, goal, stalled_on)); - unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); - } + match certainty { + Certainty::Yes => {} + Certainty::Maybe { .. } => { + self.nested_goals.push((source, goal, stalled_on)); + unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty)); } } } @@ -802,129 +721,6 @@ where } } - /// Is the projection predicate is of the form `exists ::Assoc = T`. - /// - /// 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. - #[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() { - ty::TermKind::Ty(ty) => { - if let ty::Infer(ty::TyVar(vid)) = ty.kind() { - self.delegate.universe_of_ty(vid).unwrap() - } else { - return false; - } - } - ty::TermKind::Const(ct) => { - if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() { - self.delegate.universe_of_ct(vid).unwrap() - } else { - return false; - } - } - }; - - struct ContainsTermOrNotNameable<'a, D: SolverDelegate, I: Interner> { - term: I::Term, - universe_of_term: ty::UniverseIndex, - delegate: &'a D, - cache: HashSet>, - } - - impl, I: Interner> ContainsTermOrNotNameable<'_, D, I> { - fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> { - if self.universe_of_term.can_name(universe) { - ControlFlow::Continue(()) - } else { - ControlFlow::Break(()) - } - } - } - - impl, I: Interner> TypeVisitor - for ContainsTermOrNotNameable<'_, D, I> - { - type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty) -> Self::Result { - if self.cache.contains(&t) { - return ControlFlow::Continue(()); - } - - match t.kind() { - ty::Infer(ty::TyVar(vid)) => { - if let ty::TermKind::Ty(term) = self.term.kind() - && let ty::Infer(ty::TyVar(term_vid)) = term.kind() - && self.delegate.root_ty_var(vid) == self.delegate.root_ty_var(term_vid) - { - return ControlFlow::Break(()); - } - - self.check_nameable(self.delegate.universe_of_ty(vid).unwrap())?; - } - ty::Placeholder(p) => self.check_nameable(p.universe())?, - _ => { - if t.has_non_region_infer() || t.has_placeholders() { - t.super_visit_with(self)? - } - } - } - - assert!(self.cache.insert(t)); - ControlFlow::Continue(()) - } - - fn visit_const(&mut self, c: I::Const) -> Self::Result { - match c.kind() { - ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { - if let ty::TermKind::Const(term) = self.term.kind() - && let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind() - && self.delegate.root_const_var(vid) - == self.delegate.root_const_var(term_vid) - { - return ControlFlow::Break(()); - } - - self.check_nameable(self.delegate.universe_of_ct(vid).unwrap()) - } - ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe()), - _ => { - if c.has_non_region_infer() || c.has_placeholders() { - c.super_visit_with(self) - } else { - ControlFlow::Continue(()) - } - } - } - } - - fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result { - if p.has_non_region_infer() || p.has_placeholders() { - p.super_visit_with(self) - } else { - ControlFlow::Continue(()) - } - } - - fn visit_clauses(&mut self, c: I::Clauses) -> Self::Result { - if c.has_non_region_infer() || c.has_placeholders() { - c.super_visit_with(self) - } else { - ControlFlow::Continue(()) - } - } - } - - let mut visitor = ContainsTermOrNotNameable { - delegate: self.delegate, - universe_of_term, - term: goal.predicate.term, - cache: Default::default(), - }; - goal.predicate.alias.visit_with(&mut visitor).is_continue() - && goal.param_env.visit_with(&mut visitor).is_continue() - } - pub(super) fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) { self.delegate.sub_unify_ty_vids_raw(a, b) } @@ -1423,13 +1219,12 @@ where fn fold_ty(&mut self, ty: Ty) -> 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 normalizes_to = ty::PredicateKind::NormalizesTo(ty::NormalizesTo { + alias: ty::AliasTerm::new_from_args(self.cx(), alias.def_id, alias.args), + term: infer_ty.into(), + }); self.ecx.add_goal( self.normalization_goal_source, Goal::new(self.cx(), self.param_env, normalizes_to), @@ -1452,13 +1247,12 @@ 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 normalizes_to = ty::PredicateKind::NormalizesTo(ty::NormalizesTo { + alias: ty::AliasTerm::new_from_args(self.cx(), uc.def.into(), uc.args), + term: infer_ct.into(), + }); self.ecx.add_goal( self.normalization_goal_source, Goal::new(self.cx(), self.param_env, normalizes_to), diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs index edf2a5d1ba8dc..5901bf0dc08ee 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs @@ -1,11 +1,15 @@ use std::marker::PhantomData; +use rustc_type_ir::inherent::*; use rustc_type_ir::search_graph::CandidateHeadUsages; -use rustc_type_ir::{InferCtxtLike, Interner}; +use rustc_type_ir::solve::{Certainty, Goal}; +use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use tracing::instrument; +use crate::canonical::instantiate_and_apply_query_response; use crate::delegate::SolverDelegate; use crate::solve::assembly::Candidate; +use crate::solve::eval_ctxt::CurrentGoalKind; use crate::solve::{ BuiltinImplSource, CandidateSource, EvalCtxt, NoSolution, QueryResult, inspect, }; @@ -135,4 +139,54 @@ where source, } } + + /// When probing candidates for the `NormalizesTo` goal, the projection term should be + /// fully unconstrained. This helps it by replacing the projection term to an unconstrained + /// inference var, probe with `CurrentGoalKind::NormalizesTo` to handle ambiguous nested + /// goals, instantiate and apply the response and then add those nested goals to the root + /// context. + pub(in crate::solve) fn probe_with_unconstrained_projection_term( + &mut self, + goal: Goal>, + f: impl FnOnce(&mut EvalCtxt<'_, D, I>, Goal>) -> QueryResult, + ) -> Result<(I::Term, Certainty), NoSolution> { + let cx = self.cx(); + let unconstrained_term = self.next_term_infer_of_kind(goal.predicate.term); + let unconstrained_goal = goal + .with(cx, ty::NormalizesTo { alias: goal.predicate.alias, 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(|_| inspect::ProbeKind::ShadowedEnvProbing).enter(|ecx| { + ecx.current_goal_kind = CurrentGoalKind::NormalizesTo; + ecx.var_values.var_values = extended_var_values; + ecx.var_kinds = extended_var_kinds; + f(ecx, unconstrained_goal) + })?; + + let (nested_goals, certainty) = instantiate_and_apply_query_response( + self.delegate, + goal.param_env, + extended_var_values.as_slice(), + resp, + self.origin_span, + ); + + for (source, nested_goal) in nested_goals.0 { + self.add_goal(source, nested_goal); + } + + Ok((unconstrained_term, certainty)) + } } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 71b28cf1ad277..4494f839dcc3c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -344,20 +344,16 @@ where param_env: I::ParamEnv, term: I::Term, ) -> Result { - if let Some(_) = term.to_alias_term() { + if let Some(alias) = term.to_alias_term() { let normalized_term = self.next_term_infer_of_kind(term); - let alias_relate_goal = Goal::new( + let normalizes_to_goal = Goal::new( self.cx(), param_env, - ty::PredicateKind::AliasRelate( - term, - normalized_term, - ty::AliasRelationDirection::Equate, - ), + ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term: normalized_term }), ); // We normalize the self type to be able to relate it with // types from candidates. - self.add_goal(GoalSource::TypeRelating, alias_relate_goal); + self.add_goal(GoalSource::TypeRelating, normalizes_to_goal); self.try_evaluate_added_goals()?; Ok(self.resolve_vars_if_possible(normalized_term)) } else { diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs index eb6a1b51421ca..8a7a045f795eb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs @@ -32,7 +32,7 @@ where goal.predicate.alias.args, ), ) { - self.instantiate_normalizes_to_term(goal, normalized_const.into()); + self.eq(goal.param_env, goal.predicate.term, 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/normalizes_to/free_alias.rs index 8777f84957a79..557392d5e1908 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs @@ -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.eq(goal.param_env, goal.predicate.term, 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/normalizes_to/inherent.rs index 42aa237762d9e..d19b0c83d512e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -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.eq(goal.param_env, goal.predicate.term, 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/normalizes_to/mod.rs index 13ed945857db2..2e8b5c785f4f3 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 @@ -29,7 +29,6 @@ where &mut self, goal: Goal>, ) -> QueryResult { - debug_assert!(self.term_is_fully_unconstrained(goal)); let cx = self.cx(); match goal.predicate.alias.kind(cx) { ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => { @@ -39,49 +38,65 @@ where 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 (probed_term, certainty) = + self.probe_with_unconstrained_projection_term(goal, |ecx, goal| { + ecx.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( 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_normalizes_to_term( + goal, + goal.predicate.alias, + ); + this.evaluate_added_goals_and_make_canonical_response( + Certainty::Yes, + ) + }, + ) + }, + ) + })?; + + self.eq_structurally_relating_aliases( + goal.param_env, + goal.predicate.term, + probed_term, + )?; + + self.evaluate_added_goals_and_make_canonical_response(certainty) } ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst => { self.normalize_inherent_associated_term(goal) @@ -99,18 +114,14 @@ 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( - &mut self, - goal: Goal>, - term: I::Term, - ) { + fn instantiate_normalizes_to_term(&mut self, goal: Goal>, term: I::Term) { 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 /// with a rigid alias. Using this is pretty much always wrong. - pub fn structurally_instantiate_normalizes_to_term( + fn structurally_instantiate_normalizes_to_term( &mut self, goal: Goal>, term: ty::AliasTerm, 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 a5f857a1dd85b..bcd023919647c 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 @@ -48,7 +48,12 @@ 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.relate_rigid_alias_non_alias( + goal.param_env, + goal.predicate.alias, + ty::Invariant, + goal.predicate.term, + )?; return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); }; @@ -111,7 +116,12 @@ where .as_local() .filter(|&def_id| defined_opaque_types.contains(&def_id)) else { - self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + self.relate_rigid_alias_non_alias( + goal.param_env, + goal.predicate.alias, + ty::Invariant, + goal.predicate.term, + )?; return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); }; 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 77834320dbc6b..3526050db8327 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -292,13 +292,13 @@ impl<'tcx> BestObligation<'tcx> { ) -> ControlFlow> { assert!(!self.consider_ambiguities); let tcx = goal.infcx().tcx; - if let ty::Alias(..) = self_ty.kind() { + let term: ty::Term<'tcx> = self_ty.into(); + if let Some(alias) = term.to_alias_term() { let infer_term = goal.infcx().next_ty_var(self.obligation.cause.span); - let pred = ty::PredicateKind::AliasRelate( - self_ty.into(), - infer_term.into(), - ty::AliasRelationDirection::Equate, - ); + let pred = ty::PredicateKind::NormalizesTo(ty::NormalizesTo { + alias, + term: infer_term.into(), + }); let obligation = Obligation::new(tcx, self.obligation.cause.clone(), goal.goal().param_env, pred); self.with_derived_obligation(obligation, |this| { diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 567f660a59383..7a8e27dc522d8 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -102,11 +102,10 @@ where let infcx = self.at.infcx; let tcx = infcx.tcx; let recursion_limit = tcx.recursion_limit(); + let alias = alias_term.to_alias_term().unwrap(); if !recursion_limit.value_within_limit(self.depth) { - let term = alias_term.to_alias_term().unwrap(); - self.at.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(term), + OverflowCause::DeeplyNormalize(alias), self.at.cause.span, true, |_| {}, @@ -120,11 +119,7 @@ where tcx, self.at.cause.clone(), self.at.param_env, - ty::PredicateKind::AliasRelate( - alias_term.into(), - infer_term.into(), - ty::AliasRelationDirection::Equate, - ), + ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, 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..221552d55a084 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,7 @@ impl<'tcx> At<'_, 'tcx> { self.infcx.tcx, self.cause.clone(), self.param_env, - ty::PredicateKind::AliasRelate(term, new_infer, ty::AliasRelationDirection::Equate), + ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term: new_infer }), ); fulfill_cx.register_predicate_obligation(self.infcx, obligation); diff --git a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr index b6636d4de86eb..120bffed7c4ec 100644 --- a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr +++ b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot normalize ` as Object>::Output` +error[E0284]: type annotations needed: cannot satisfy ` as Object>::Output normalizes-to T` --> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:41 | LL | foo::, U>(x) - | ^ cannot normalize ` as Object>::Output` + | ^ cannot satisfy ` as Object>::Output normalizes-to T` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs index abfd51c2008bb..a5c3384d0d7da 100644 --- a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs +++ b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs @@ -23,7 +23,7 @@ fn foo(x: >::Output) -> U { #[allow(dead_code)] fn transmute(x: T) -> U { foo::, U>(x) - //[next]~^ ERROR type annotations needed: cannot normalize ` as Object>::Output` + //[next]~^ ERROR type annotations needed: cannot satisfy ` as Object>::Output normalizes-to T` } fn main() {} diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 381f5c60f9831..a296f95abbbd2 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -14,11 +14,11 @@ LL | | for<'a> *const T: ToUnit<'a>, | = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details -error[E0284]: type annotations needed: cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` +error[E0284]: type annotations needed: cannot satisfy ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc normalizes-to usize` --> $DIR/associated-type.rs:45:59 | LL | foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); - | ^^^^^^ cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` + | ^^^^^^ cannot satisfy ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc normalizes-to usize` error: aborting due to 2 previous errors diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs index d56ccc5b3532d..7e8b24e3a60bc 100644 --- a/tests/ui/coherence/occurs-check/associated-type.rs +++ b/tests/ui/coherence/occurs-check/associated-type.rs @@ -43,5 +43,5 @@ fn foo, U>(x: T::Assoc) -> T::Assoc { fn main() { foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); - //[next]~^ ERROR: cannot normalize + //[next]~^ ERROR: type annotations needed: cannot satisfy ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc normalizes-to usize` } diff --git a/tests/ui/const-generics/mgca/free-const-recursive.rs b/tests/ui/const-generics/mgca/free-const-recursive.rs index 8d75c1a941a77..93f803fca2512 100644 --- a/tests/ui/const-generics/mgca/free-const-recursive.rs +++ b/tests/ui/const-generics/mgca/free-const-recursive.rs @@ -5,7 +5,7 @@ #![expect(incomplete_features)] type const A: () = A; -//~^ ERROR type mismatch resolving `A normalizes-to _` +//~^ ERROR type mismatch resolving `_ == A` //~| ERROR the constant `A` is not of type `()` fn main() { diff --git a/tests/ui/const-generics/mgca/free-const-recursive.stderr b/tests/ui/const-generics/mgca/free-const-recursive.stderr index d0f10275b40d2..230a588d0aa29 100644 --- a/tests/ui/const-generics/mgca/free-const-recursive.stderr +++ b/tests/ui/const-generics/mgca/free-const-recursive.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `A normalizes-to _` +error[E0271]: type mismatch resolving `_ == A` --> $DIR/free-const-recursive.rs:7:1 | LL | type const A: () = A; diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr index f2e249f2cbf99..9b0e9eda01e3f 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr @@ -25,25 +25,19 @@ LL | type LineStream<'c, 'd> = impl Stream; | = note: `LineStream` must be used in combination with a concrete type within the same impl -error[E0271]: type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to ()` +error[E0271]: type mismatch resolving `::LineStreamFut<'a, Repr> == ()` --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:43 | LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ -error[E0271]: type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` - --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:73 - | -LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} - | ^^ types differ - error[E0271]: type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:5 | LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0049, E0271, E0407. For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs index 7cf155ce01ef4..736e00e12c568 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs @@ -29,8 +29,7 @@ impl X for Y { fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} //~^ ERROR method `line_stream` is not a member of trait `X` //[current]~^^ ERROR `()` is not a future - //[next]~^^^ ERROR type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to ()` - //[next]~| ERROR type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` + //[next]~^^^ ERROR type mismatch resolving `::LineStreamFut<'a, Repr> == ()` //[next]~| ERROR type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` } diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr index 62ed6e8e513d9..e10d32366d77e 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr @@ -1,22 +1,22 @@ -error[E0271]: type mismatch resolving `Loop normalizes-to _` +error[E0271]: type mismatch resolving `_ == Loop` --> $DIR/inherent-impls-overflow.rs:8:1 | LL | type Loop = Loop; | ^^^^^^^^^ types differ -error[E0271]: type mismatch resolving `Loop normalizes-to _` +error[E0271]: type mismatch resolving `_ == Loop` --> $DIR/inherent-impls-overflow.rs:12:1 | LL | impl Loop {} | ^^^^^^^^^^^^ types differ -error[E0271]: type mismatch resolving `Loop normalizes-to _` +error[E0271]: type mismatch resolving `_ == Loop` --> $DIR/inherent-impls-overflow.rs:12:6 | LL | impl Loop {} | ^^^^ types differ -error[E0275]: overflow evaluating the requirement `Poly1<(T,)> == _` +error[E0275]: overflow evaluating the requirement `Poly1<(T,)> normalizes-to _` --> $DIR/inherent-impls-overflow.rs:17:1 | LL | type Poly0 = Poly1<(T,)>; @@ -35,7 +35,7 @@ LL | type Poly0 = Poly1<(T,)>; = help: consider removing `T` or referring to it in the body of the type alias = note: all type parameters must be used in a non-recursive way in order to constrain their variance -error[E0275]: overflow evaluating the requirement `Poly0<(T,)> == _` +error[E0275]: overflow evaluating the requirement `Poly0<(T,)> normalizes-to _` --> $DIR/inherent-impls-overflow.rs:21:1 | LL | type Poly1 = Poly0<(T,)>; @@ -54,7 +54,7 @@ LL | type Poly1 = Poly0<(T,)>; = help: consider removing `T` or referring to it in the body of the type alias = note: all type parameters must be used in a non-recursive way in order to constrain their variance -error[E0275]: overflow evaluating the requirement `Poly0<()> == _` +error[E0275]: overflow evaluating the requirement `Poly0<()> normalizes-to _` --> $DIR/inherent-impls-overflow.rs:26:1 | LL | impl Poly0<()> {} @@ -62,7 +62,7 @@ LL | impl Poly0<()> {} | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`) -error[E0275]: overflow evaluating the requirement `Poly0<()> == _` +error[E0275]: overflow evaluating the requirement `Poly0<()> normalizes-to _` --> $DIR/inherent-impls-overflow.rs:26:6 | LL | impl Poly0<()> {} diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs index b4a347cb098ca..b1e9c5b48e62b 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs @@ -7,12 +7,12 @@ type Loop = Loop; //[current]~^ ERROR overflow normalizing the type alias `Loop` -//[next]~^^ ERROR type mismatch resolving `Loop normalizes-to _` +//[next]~^^ ERROR type mismatch resolving `_ == Loop` impl Loop {} //[current]~^ ERROR overflow normalizing the type alias `Loop` -//[next]~^^ ERROR type mismatch resolving `Loop normalizes-to _` -//[next]~| ERROR type mismatch resolving `Loop normalizes-to _` +//[next]~^^ ERROR type mismatch resolving `_ == Loop` +//[next]~| ERROR type mismatch resolving `_ == Loop` type Poly0 = Poly1<(T,)>; //[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>` @@ -25,7 +25,7 @@ type Poly1 = Poly0<(T,)>; impl Poly0<()> {} //[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` -//[next]~^^ ERROR overflow evaluating the requirement `Poly0<()> == _` +//[next]~^^ ERROR overflow evaluating the requirement `Poly0<()> normalizes-to _` //[next]~| ERROR overflow evaluating the requirement fn main() {} diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs index 14f0cbcc8b77c..eef7bb0130dc6 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs @@ -13,9 +13,9 @@ fn main() { } fn weird0() -> impl Sized + !Sized {} -//~^ ERROR the trait bound `(): !Sized` is not satisfied +//~^ ERROR type mismatch resolving `impl !Sized + Sized == ()` fn weird1() -> impl !Sized + Sized {} -//~^ ERROR the trait bound `(): !Sized` is not satisfied +//~^ ERROR type mismatch resolving `impl !Sized + Sized == ()` fn weird2() -> impl !Sized {} -//~^ ERROR the trait bound `(): !Sized` is not satisfied +//~^ ERROR type mismatch resolving `impl !Sized == ()` //~| ERROR the size for values of type diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr index 3ba3d8d8bd595..41d9e74f8076e 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr @@ -7,23 +7,23 @@ LL | fn weird2() -> impl !Sized {} = help: the trait `Sized` is not implemented for `impl !Sized` = note: the return type of a function must have a statically known size -error[E0277]: the trait bound `(): !Sized` is not satisfied +error[E0271]: type mismatch resolving `impl !Sized + Sized == ()` --> $DIR/opaque-type-unsatisfied-bound.rs:15:16 | LL | fn weird0() -> impl Sized + !Sized {} - | ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied + | ^^^^^^^^^^^^^^^^^^^ types differ -error[E0277]: the trait bound `(): !Sized` is not satisfied +error[E0271]: type mismatch resolving `impl !Sized + Sized == ()` --> $DIR/opaque-type-unsatisfied-bound.rs:17:16 | LL | fn weird1() -> impl !Sized + Sized {} - | ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied + | ^^^^^^^^^^^^^^^^^^^ types differ -error[E0277]: the trait bound `(): !Sized` is not satisfied +error[E0271]: type mismatch resolving `impl !Sized == ()` --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 | LL | fn weird2() -> impl !Sized {} - | ^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied + | ^^^^^^^^^^^ types differ error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:12:13 @@ -41,4 +41,5 @@ LL | fn consume(_: impl Trait) {} error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs index 39422914afcdd..9951826a8466d 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs @@ -3,6 +3,6 @@ #![feature(negative_bounds, unboxed_closures)] fn produce() -> impl !Fn<(u32,)> {} -//~^ ERROR the trait bound `(): !Fn(u32)` is not satisfied +//~^ ERROR type mismatch resolving `impl !Fn<(u32,)> == ()` fn main() {} diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr index 760e5aa62f2c1..e1b84e0df7a54 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr @@ -1,9 +1,9 @@ -error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied +error[E0271]: type mismatch resolving `impl !Fn<(u32,)> == ()` --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17 | LL | fn produce() -> impl !Fn<(u32,)> {} - | ^^^^^^^^^^^^^^^^ the trait bound `(): !Fn(u32)` is not satisfied + | ^^^^^^^^^^^^^^^^ types differ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index b2015b336b24a..c7dfaa07aae60 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -29,8 +29,8 @@ fn main() { //~^ ERROR overflow evaluating whether `<() as Foo>::Item` is well-formed //~| ERROR overflow evaluating whether `&<() as Foo>::Item` is well-formed //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == String` - //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` - //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` - //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` + //~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _` + //~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _` + //~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _` println!("{x}"); } diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr index ebfaf469ddf89..feeeae3f224fb 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -18,13 +18,13 @@ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == String` LL | let _ = identity(<() as Foo>::copy_me(&x)); | ^^ -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _` --> $DIR/alias-bound-unsound.rs:28:22 | LL | let _ = identity(<() as Foo>::copy_me(&x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _` --> $DIR/alias-bound-unsound.rs:28:22 | LL | let _ = identity(<() as Foo>::copy_me(&x)); @@ -44,7 +44,7 @@ error[E0275]: overflow evaluating whether `<() as Foo>::Item` is well-formed LL | let _ = identity(<() as Foo>::copy_me(&x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _` --> $DIR/alias-bound-unsound.rs:28:22 | LL | let _ = identity(<() as Foo>::copy_me(&x)); diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr index 61c6ef9a449ef..7698881f3cfd2 100644 --- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr @@ -1,21 +1,21 @@ -error[E0283]: type annotations needed: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>` - --> $DIR/ambiguity-due-to-uniquification-2.rs:16:5 +error[E0271]: type mismatch resolving `foo<'_, '_>::{opaque#0}<'_, '_> normalizes-to impl Trait<'_> + Trait<'_>` + --> $DIR/ambiguity-due-to-uniquification-2.rs:16:26 | LL | impls_trait::<'y, _>(foo::<'x, 'y>()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>` -help: the trait `Trait<'t>` is implemented for `()` - --> $DIR/ambiguity-due-to-uniquification-2.rs:9:1 + | ^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `foo<'_, '_>::{opaque#0}<'_, '_> normalizes-to impl Trait<'_> + Trait<'_>` + --> $DIR/ambiguity-due-to-uniquification-2.rs:16:5 | -LL | impl<'t> Trait<'t> for () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required by a bound in `impls_trait` - --> $DIR/ambiguity-due-to-uniquification-2.rs:13:23 +LL | impls_trait::<'y, _>(foo::<'x, 'y>()); + | ^^^^^^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `foo<'_, '_>::{opaque#0}<'_, '_> normalizes-to impl Trait<'_> + Trait<'_>` + --> $DIR/ambiguity-due-to-uniquification-2.rs:16:23 | -LL | fn impls_trait<'x, T: Trait<'x>>(_: T) {} - | ^^^^^^^^^ required by this bound in `impls_trait` +LL | impls_trait::<'y, _>(foo::<'x, 'y>()); + | ^ types differ -error: aborting due to 1 previous error +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs index 30df70396f448..3a30a043242fe 100644 --- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs @@ -14,7 +14,9 @@ fn impls_trait<'x, T: Trait<'x>>(_: T) {} fn bar<'x, 'y>() { impls_trait::<'y, _>(foo::<'x, 'y>()); - //[next]~^ ERROR type annotations needed: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>` + //[next]~^ ERROR type mismatch resolving `foo<'_, '_>::{opaque#0}<'_, '_> normalizes-to impl Trait<'_> + Trait<'_>` + //[next]~| ERROR type mismatch resolving `foo<'_, '_>::{opaque#0}<'_, '_> normalizes-to impl Trait<'_> + Trait<'_>` + //[next]~| ERROR type mismatch resolving `foo<'_, '_>::{opaque#0}<'_, '_> normalizes-to impl Trait<'_> + Trait<'_>` } fn main() {} diff --git a/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.next.stderr b/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.next.stderr index ed6e595d0afbe..5712efc57b032 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.next.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.next.stderr @@ -10,13 +10,13 @@ note: required by a bound in `transmute` LL | fn transmute, R>(r: L) -> >::Proof { r } | ^^^^^^^^ required by this bound in `transmute` -error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == _` +error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof normalizes-to _` --> $DIR/item-bound-via-impl-where-clause.rs:31:21 | LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == String` +error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof normalizes-to String` --> $DIR/item-bound-via-impl-where-clause.rs:31:21 | LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); @@ -36,7 +36,7 @@ error[E0275]: overflow evaluating whether `< as Trait>::Proof as LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == _` +error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof normalizes-to _` --> $DIR/item-bound-via-impl-where-clause.rs:31:21 | LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); diff --git a/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.rs b/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.rs index 6ac0c1481c79a..321b1f20f2dd4 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.rs +++ b/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.rs @@ -30,10 +30,10 @@ fn transmute, R>(r: L) -> >::Proof { r } fn main() { let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); //~^ ERROR overflow evaluating the requirement `Vec: Trait` - //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == _` - //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == String` + //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof normalizes-to _` + //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof normalizes-to String` //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof: Sized` //[next]~| ERROR overflow evaluating whether `< as Trait>::Proof as Trait>::Proof` is well-formed - //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == _` + //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof normalizes-to _` println!("{}", s); // ABC } diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr index cb1bbd4c61716..dd0f440edf567 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `<() as A>::Assoc == _` +error[E0275]: overflow evaluating the requirement `<() as A>::Assoc normalizes-to _` --> $DIR/normalize-param-env-2.rs:22:5 | LL | / fn f() diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs index 5239474ff44b2..cc9d9b9081026 100644 --- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs +++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs @@ -24,7 +24,7 @@ fn needs_bar() {} fn foo + Foo>() { needs_bar::(); - //~^ ERROR type annotations needed: cannot normalize + //~^ ERROR type annotations needed: cannot satisfy `::Assoc normalizes-to i32` } fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr index 270ad85171779..23ec9d87bcfe0 100644 --- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr +++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot normalize `::Assoc` +error[E0284]: type annotations needed: cannot satisfy `::Assoc normalizes-to i32` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17 | LL | needs_bar::(); - | ^ cannot normalize `::Assoc` + | ^ cannot satisfy `::Assoc normalizes-to i32` | note: required for `T` to implement `Bar` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9 diff --git a/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr b/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr index 6afa406bf367e..e99257c22653d 100644 --- a/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr +++ b/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr @@ -29,13 +29,13 @@ note: captured value does not implement `Valid` LL | let foo: T = async { a }; | ^ has type `False` which does not implement `Valid` -error[E0271]: type mismatch resolving `impl Future + Send == {async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19}` +error[E0271]: type mismatch resolving `impl Future + Send normalizes-to {async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19}` --> $DIR/stalled-coroutine-obligations.rs:39:5 | LL | fn stalled_send(&self, b: *mut ()) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ -error[E0271]: type mismatch resolving `impl Future + Send == {async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19}` +error[E0271]: type mismatch resolving `impl Future + Send normalizes-to {async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19}` --> $DIR/stalled-coroutine-obligations.rs:42:9 | LL | / async move { diff --git a/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr b/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr index bf8d3c40cf653..2a81d6e951589 100644 --- a/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr +++ b/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr @@ -1,3 +1,17 @@ +error[E0271]: type mismatch resolving `::Assert normalizes-to _` + --> $DIR/trivial-unsized-projection-2.rs:22:12 + | +LL | const FOO: ::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `::Assert normalizes-to _` + --> $DIR/trivial-unsized-projection-2.rs:22:12 + | +LL | const FOO: ::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ types differ + | + = note: statics and constants must have a statically known size + error[E0277]: the size for values of type `[()]` cannot be known at compilation time --> $DIR/trivial-unsized-projection-2.rs:22:12 | @@ -49,6 +63,21 @@ help: consider relaxing the implicit `Sized` restriction LL | type Assert: ?Sized | ++++++++ -error: aborting due to 2 previous errors +error[E0271]: type mismatch resolving `::Assert normalizes-to _` + --> $DIR/trivial-unsized-projection-2.rs:22:36 + | +LL | const FOO: ::Assert = todo!(); + | ^^^^^^^ types differ + +error[E0271]: type mismatch resolving `::Assert normalizes-to _` + --> $DIR/trivial-unsized-projection-2.rs:22:36 + | +LL | const FOO: ::Assert = todo!(); + | ^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/trivial-unsized-projection-2.rs b/tests/ui/traits/trivial-unsized-projection-2.rs index af4e12f6f9008..ca9cf9a3106dc 100644 --- a/tests/ui/traits/trivial-unsized-projection-2.rs +++ b/tests/ui/traits/trivial-unsized-projection-2.rs @@ -24,6 +24,10 @@ const FOO: ::Assert = todo!(); //[bad]~| ERROR the size for values of type `[()]` cannot be known at compilation time //[bad_new]~^^^ ERROR the size for values of type `[()]` cannot be known at compilation time //[bad_new]~| ERROR the size for values of type `[()]` cannot be known at compilation time +//[bad_new]~| ERROR type mismatch resolving `::Assert normalizes-to _` +//[bad_new]~| ERROR type mismatch resolving `::Assert normalizes-to _` +//[bad_new]~| ERROR type mismatch resolving `::Assert normalizes-to _` +//[bad_new]~| ERROR type mismatch resolving `::Assert normalizes-to _` #[cfg(any(good, good_new))] // Well-formed in trivially false param-env diff --git a/tests/ui/traits/trivial-unsized-projection.bad_new.stderr b/tests/ui/traits/trivial-unsized-projection.bad_new.stderr index 4aea63329b360..886a75918d3d0 100644 --- a/tests/ui/traits/trivial-unsized-projection.bad_new.stderr +++ b/tests/ui/traits/trivial-unsized-projection.bad_new.stderr @@ -1,3 +1,17 @@ +error[E0271]: type mismatch resolving `<[()] as Bad>::Assert normalizes-to _` + --> $DIR/trivial-unsized-projection.rs:20:12 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `<[()] as Bad>::Assert normalizes-to _` + --> $DIR/trivial-unsized-projection.rs:20:12 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ types differ + | + = note: statics and constants must have a statically known size + error[E0277]: the size for values of type `[()]` cannot be known at compilation time --> $DIR/trivial-unsized-projection.rs:20:12 | @@ -39,6 +53,21 @@ help: consider relaxing the implicit `Sized` restriction LL | type Assert: ?Sized | ++++++++ -error: aborting due to 2 previous errors +error[E0271]: type mismatch resolving `<[()] as Bad>::Assert normalizes-to _` + --> $DIR/trivial-unsized-projection.rs:20:36 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^ types differ + +error[E0271]: type mismatch resolving `<[()] as Bad>::Assert normalizes-to _` + --> $DIR/trivial-unsized-projection.rs:20:36 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/trivial-unsized-projection.rs b/tests/ui/traits/trivial-unsized-projection.rs index 62ff25fb7ac0a..9a730cc7da0a5 100644 --- a/tests/ui/traits/trivial-unsized-projection.rs +++ b/tests/ui/traits/trivial-unsized-projection.rs @@ -22,6 +22,10 @@ const FOO: <[()] as Bad>::Assert = todo!(); //[bad]~| ERROR the size for values of type `[()]` cannot be known at compilation time //[bad_new]~^^^ ERROR the size for values of type `[()]` cannot be known at compilation time //[bad_new]~| ERROR the size for values of type `[()]` cannot be known at compilation time +//[bad_new]~| ERROR type mismatch resolving `<[()] as Bad>::Assert normalizes-to _` +//[bad_new]~| ERROR type mismatch resolving `<[()] as Bad>::Assert normalizes-to _` +//[bad_new]~| ERROR type mismatch resolving `<[()] as Bad>::Assert normalizes-to _` +//[bad_new]~| ERROR type mismatch resolving `<[()] as Bad>::Assert normalizes-to _` #[cfg(any(good, good_new))] // Well-formed in trivially false param-env diff --git a/tests/ui/traits/unconstrained-projection-normalization-2.next.stderr b/tests/ui/traits/unconstrained-projection-normalization-2.next.stderr index 2da655afa935c..9ce0e8d957dab 100644 --- a/tests/ui/traits/unconstrained-projection-normalization-2.next.stderr +++ b/tests/ui/traits/unconstrained-projection-normalization-2.next.stderr @@ -28,13 +28,7 @@ help: consider relaxing the implicit `Sized` restriction LL | type Assoc: ?Sized; | ++++++++ -error[E0282]: type annotations needed - --> $DIR/unconstrained-projection-normalization-2.rs:20:11 - | -LL | fn foo(_: ::Assoc) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for associated type `::Assoc` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0207, E0277, E0282. +Some errors have detailed explanations: E0207, E0277. For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/traits/unconstrained-projection-normalization-2.rs b/tests/ui/traits/unconstrained-projection-normalization-2.rs index 899d67571e710..1d45d525c04c3 100644 --- a/tests/ui/traits/unconstrained-projection-normalization-2.rs +++ b/tests/ui/traits/unconstrained-projection-normalization-2.rs @@ -18,6 +18,5 @@ impl Every for Thing { } fn foo(_: ::Assoc) {} -//[next]~^ ERROR: type annotations needed fn main() {}