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 652f0498b5841..615b7d7524a86 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -41,7 +41,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.type_matches_expected_vid(expected_vid, data.self_ty()) } ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { - self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty()) + if data.projection_term.kind.is_trait_projection() { + self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty()) + } else { + false + } } ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::PredicateKind::Subtype(..) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index c9ec32159f476..164c1287ca4f5 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1816,6 +1816,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let pred = bound_predicate.rebind(pred); // `::Item = String`. let projection_term = pred.skip_binder().projection_term; + if !projection_term.kind.is_trait_projection() { + return None; + } + let quiet_projection_term = projection_term .with_replaced_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO)); diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index c3194e4d8acd3..8322bc2581b70 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -333,12 +333,10 @@ impl<'tcx> InferCtxt<'tcx> { goals.push(Goal::new( self.tcx, param_env, - ty::PredicateKind::Clause(ty::ClauseKind::Projection( - ty::ProjectionPredicate { - projection_term: projection_ty.into(), - term: ty_var.into(), - }, - )), + ty::ProjectionPredicate { + projection_term: projection_ty.into(), + term: ty_var.into(), + }, )); ty_var } diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index c3a5a8a5d818d..f8d754e877415 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -29,11 +29,7 @@ impl<'tcx> InferCtxt<'tcx> { self.next_const_var(span).into() }; - let projection = - ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_term: alias_term, - term: infer_var, - })); + let projection = ty::ProjectionPredicate { projection_term: alias_term, term: infer_var }; let obligation = Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection); obligations.push(obligation); diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index 7506591d6fb5d..5bce8fa2e7634 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -2,8 +2,8 @@ use rustc_type_ir::data_structures::ensure_sufficient_stack; use rustc_type_ir::inherent::*; use rustc_type_ir::solve::{Goal, NoSolution}; use rustc_type_ir::{ - self as ty, Binder, FallibleTypeFolder, InferConst, InferCtxtLike, InferTy, Interner, - TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + self as ty, AliasTerm, Binder, FallibleTypeFolder, InferConst, InferCtxtLike, InferTy, + Interner, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UniverseIndex, }; use tracing::instrument; @@ -101,7 +101,7 @@ impl<'a, Infcx, I, F> NormalizationFolder<'a, Infcx, I, F> where Infcx: InferCtxtLike, I: Interner, - F: FnMut(I::Term) -> Result<(I::Term, Option>), NoSolution>, + F: FnMut(AliasTerm) -> Result<(I::Term, Option>), NoSolution>, { pub fn new( infcx: &'a Infcx, @@ -118,7 +118,7 @@ where fn normalize_alias_term( &mut self, - alias_term: I::Term, + alias_term: AliasTerm, has_escaping: HasEscapingBoundVars, ) -> Result { let current_universe = self.infcx.universe(); @@ -139,7 +139,7 @@ where normalized.visit_with(&mut visitor); let max_universe = visitor.max_universe(); if current_universe.cannot_name(max_universe) { - return Ok(alias_term); + return Ok(alias_term.to_term(self.cx())); } } @@ -152,7 +152,7 @@ impl<'a, Infcx, I, F> FallibleTypeFolder for NormalizationFolder<'a, Infcx, I where Infcx: InferCtxtLike, I: Interner, - F: FnMut(I::Term) -> Result<(I::Term, Option>), NoSolution>, + F: FnMut(AliasTerm) -> Result<(I::Term, Option>), NoSolution>, { type Error = NoSolution; @@ -180,13 +180,13 @@ where // With eager normalization, we should normalize the args of alias before // normalizing the alias itself. let ty = ty.try_super_fold_with(self)?; - let ty::Alias(..) = ty.kind() else { return Ok(ty) }; + let ty::Alias(alias_ty) = ty.kind() else { return Ok(ty) }; if ty.has_escaping_bound_vars() { - let (ty, mapped_regions, mapped_types, mapped_consts) = - BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty); + let (alias_ty, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, alias_ty); let result = ensure_sufficient_stack(|| { - self.normalize_alias_term(ty.into(), HasEscapingBoundVars::Yes) + self.normalize_alias_term(alias_ty.into(), HasEscapingBoundVars::Yes) })? .expect_ty(); Ok(PlaceholderReplacer::replace_placeholders( @@ -199,7 +199,7 @@ where )) } else { Ok(ensure_sufficient_stack(|| { - self.normalize_alias_term(ty.into(), HasEscapingBoundVars::No) + self.normalize_alias_term(alias_ty.into(), HasEscapingBoundVars::No) })? .expect_ty()) } @@ -215,13 +215,13 @@ where // With eager normalization, we should normalize the args of alias before // normalizing the alias itself. let ct = ct.try_super_fold_with(self)?; - let ty::ConstKind::Unevaluated(..) = ct.kind() else { return Ok(ct) }; + let ty::ConstKind::Unevaluated(uc) = ct.kind() else { return Ok(ct) }; if ct.has_escaping_bound_vars() { - let (ct, mapped_regions, mapped_types, mapped_consts) = - BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ct); + let (uc, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uc); let result = ensure_sufficient_stack(|| { - self.normalize_alias_term(ct.into(), HasEscapingBoundVars::Yes) + self.normalize_alias_term(uc.into(), HasEscapingBoundVars::Yes) })? .expect_const(); Ok(PlaceholderReplacer::replace_placeholders( @@ -234,7 +234,7 @@ where )) } else { Ok(ensure_sufficient_stack(|| { - self.normalize_alias_term(ct.into(), HasEscapingBoundVars::No) + self.normalize_alias_term(uc.into(), HasEscapingBoundVars::No) })? .expect_const()) } 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 b7e2101577eb2..a946689eda4ec 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,7 @@ 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::ProjectionPredicate { projection_term: alias, term }), ); term } else { @@ -64,7 +64,7 @@ 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::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 23fcfc2788656..cf507f9efda71 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -8,7 +8,7 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::region_constraint::RegionConstraint; use rustc_type_ir::relate::Relate; use rustc_type_ir::relate::solver_relating::RelateExt; -use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind}; +use rustc_type_ir::search_graph::{CandidateHeadUsages, IncreaseDepthForNested, PathKind}; use rustc_type_ir::solve::{ AccessedOpaques, ExternalRegionConstraints, FetchEligibleAssocItemResponse, MaybeInfo, NoSolutionOrRerunNonErased, OpaqueTypesJank, QueryResultOrRerunNonErased, RerunCondition, @@ -59,7 +59,7 @@ enum CurrentGoalKind { /// 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` + /// caller when then adds these to its own context. The caller is always an `Projection` /// goal so this never leaks out of the solver. NormalizesTo, } @@ -469,7 +469,7 @@ where stalled_on: Option>, ) -> Result, NoSolutionOrRerunNonErased> { let (normalization_nested_goals, goal_evaluation) = - self.evaluate_goal_raw(source, goal, stalled_on)?; + self.evaluate_goal_raw(source, goal, stalled_on, IncreaseDepthForNested::Yes)?; assert!(normalization_nested_goals.is_empty()); Ok(goal_evaluation) } @@ -478,7 +478,7 @@ where /// the nested goal is a `NormalizesTo` goal. /// /// As all other goal kinds do not return any nested goals and - /// `NormalizesTo` is only used by `AliasRelate`, all other callsites + /// `NormalizesTo` is only used by `Projection`, all other callsites /// should use [`EvalCtxt::evaluate_goal`] which discards that empty /// storage. pub(super) fn evaluate_goal_raw( @@ -486,6 +486,7 @@ where source: GoalSource, goal: Goal, stalled_on: Option>, + increase_depth_for_nested: IncreaseDepthForNested, ) -> Result<(NestedNormalizationGoals, GoalEvaluation), NoSolutionOrRerunNonErased> { // If we have run this goal before, and it was stalled, check that any of the goal's // args have changed. Otherwise, we don't need to re-run the goal because it'll remain @@ -576,6 +577,7 @@ where self.cx(), canonical_goal, step_kind, + increase_depth_for_nested, &mut inspect::ProofTreeBuilder::new_noop(), ); @@ -603,6 +605,7 @@ where self.cx(), canonical_goal, step_kind, + increase_depth_for_nested, &mut inspect::ProofTreeBuilder::new_noop(), ); assert!( @@ -677,17 +680,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() { @@ -912,10 +904,12 @@ where fn evaluate_added_goals_step( &mut self, ) -> Result, NoSolutionOrRerunNonErased> { - 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) { + // We never handle `NormalizesTo` as a nested goal + assert!(!matches!(goal.predicate.kind().skip_binder(), PredicateKind::NormalizesTo(_))); + if !self.delegate.disable_trait_solver_fast_paths() && let Some(certainty) = self.delegate.compute_goal_fast_path(goal, self.origin_span) @@ -930,92 +924,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; - } + 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, 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; - } - - 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)); } } } @@ -1032,10 +951,20 @@ where self.delegate.cx() } + pub(super) fn add_goal(&mut self, source: GoalSource, goal: Goal) { + self.add_goal_raw(source, goal, true); + } + #[instrument(level = "debug", skip(self))] - pub(super) fn add_goal(&mut self, source: GoalSource, mut goal: Goal) { - goal.predicate = - goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env)); + fn add_goal_raw( + &mut self, + source: GoalSource, + mut goal: Goal, + replace_alias: bool, + ) { + if replace_alias { + goal.predicate = self.replace_alias_with_infer(goal.predicate, source, goal.param_env); + } self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal); self.nested_goals.push((source, goal, None)); } @@ -1051,6 +980,15 @@ where } } + pub(super) fn replace_alias_with_infer>( + &mut self, + value: T, + source: GoalSource, + param_env: I::ParamEnv, + ) -> T { + value.fold_with(&mut ReplaceAliasWithInfer::new(self, source, param_env)) + } + pub(super) fn next_region_var(&mut self) -> I::Region { let region = self.delegate.next_region_infer(); self.inspect.add_var_value(region); @@ -1472,14 +1410,16 @@ where Ok(self.delegate.evaluate_const(param_env, uv)) } - pub(super) fn evaluate_const_and_instantiate_normalizes_to_term( + pub(super) fn evaluate_const_and_instantiate_projection_term( &mut self, - goal: Goal>, + param_env: I::ParamEnv, + projection_term: ty::AliasTerm, + expected_term: I::Term, uv: ty::UnevaluatedConst, ) -> QueryResultOrRerunNonErased { - match self.evaluate_const(goal.param_env, uv)? { + match self.evaluate_const(param_env, uv)? { Some(evaluated) => { - self.instantiate_normalizes_to_term(goal, evaluated.into()); + self.eq(param_env, expected_term, evaluated.into())?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } None if self.cx().features().generic_const_args() => { @@ -1499,7 +1439,12 @@ where // however, we want to structurally instantiate to the original, non-rebased, // trait `Self` form of the constant (with generic arguments being the trait // `Self` type). - self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + self.relate_rigid_alias_non_alias( + param_env, + projection_term, + ty::Invariant, + expected_term, + )?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } @@ -1793,16 +1738,16 @@ 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, - ); - self.ecx.add_goal( + let projection = ty::ProjectionPredicate { + projection_term: alias.into(), + term: infer_ty.into(), + }; + self.ecx.add_goal_raw( self.normalization_goal_source, - Goal::new(self.cx(), self.param_env, normalizes_to), + Goal::new(self.cx(), self.param_env, projection), + false, ); infer_ty } @@ -1822,16 +1767,14 @@ 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, - ); - self.ecx.add_goal( + let projection = + ty::ProjectionPredicate { projection_term: uc.into(), term: infer_ct.into() }; + self.ecx.add_goal_raw( self.normalization_goal_source, - Goal::new(self.cx(), self.param_env, normalizes_to), + Goal::new(self.cx(), self.param_env, projection), + false, ); infer_ct } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index c27597c324271..596ede6ea80b6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -368,20 +368,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 projection_goal = Goal::new( self.cx(), param_env, - ty::PredicateKind::AliasRelate( - term, - normalized_term, - ty::AliasRelationDirection::Equate, - ), + ty::ProjectionPredicate { projection_term: 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, projection_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/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs similarity index 97% rename from compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs rename to compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs index e4c3cc110e3db..92891c02c5cb6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs @@ -1,8 +1,3 @@ -mod anon_const; -mod free_alias; -mod inherent; -mod opaque_types; - use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem}; @@ -39,19 +34,12 @@ where ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } => { self.normalize_associated_term(goal) } - ty::AliasTermKind::InherentTy { def_id } => { - self.normalize_inherent_associated_term(goal, def_id.into()) - } - ty::AliasTermKind::InherentConst { def_id } => { - self.normalize_inherent_associated_term(goal, def_id.into()) - } - ty::AliasTermKind::OpaqueTy { def_id } => self.normalize_opaque_type(goal, def_id), - ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } => { - self.normalize_free_alias(goal).map_err(Into::into) - } - ty::AliasTermKind::AnonConst { def_id } => { - self.normalize_anon_const(goal, def_id).map_err(Into::into) - } + ty::AliasTermKind::InherentTy { .. } + | ty::AliasTermKind::InherentConst { .. } + | ty::AliasTermKind::OpaqueTy { .. } + | ty::AliasTermKind::FreeTy { .. } + | ty::AliasTermKind::FreeConst { .. } + | ty::AliasTermKind::AnonConst { .. } => unreachable!(), } } @@ -121,18 +109,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, @@ -423,7 +407,12 @@ where }, target_args, ); - return ecx.evaluate_const_and_instantiate_normalizes_to_term(goal, uv); + return ecx.evaluate_const_and_instantiate_projection_term( + goal.param_env, + goal.predicate.alias, + goal.predicate.term, + uv, + ); } kind => panic!("expected projection, found {kind:?}"), }; 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 af6d0aad25597..0000000000000 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs +++ /dev/null @@ -1,32 +0,0 @@ -use rustc_type_ir::solve::QueryResultOrRerunNonErased; -use rustc_type_ir::{self as ty, Interner, ProjectionPredicate}; -use tracing::instrument; - -use crate::delegate::SolverDelegate; -use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource}; - -impl EvalCtxt<'_, D> -where - D: SolverDelegate, - I: Interner, -{ - #[instrument(level = "trace", skip(self), ret)] - pub(super) fn compute_projection_goal( - &mut self, - goal: Goal>, - ) -> QueryResultOrRerunNonErased { - 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 61% 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 38197c8c72de2..d7aec8ce70641 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 @@ -13,10 +13,15 @@ where #[instrument(level = "trace", skip(self), ret)] pub(super) fn normalize_anon_const( &mut self, - goal: Goal>, + goal: Goal>, def_id: I::UnevaluatedConstId, ) -> QueryResultOrRerunNonErased { - let uv = goal.predicate.alias.expect_ct(); - self.evaluate_const_and_instantiate_normalizes_to_term(goal, uv) + let uv = goal.predicate.projection_term.expect_ct(); + self.evaluate_const_and_instantiate_projection_term( + goal.param_env, + goal.predicate.projection_term, + goal.predicate.term, + uv, + ) } } 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 80% 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 ad050b69425c5..bebff3fb61ff3 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 @@ -1,4 +1,4 @@ -//! Computes a normalizes-to (projection) goal for inherent associated types, +//! Computes a projection goal for inherent associated types, //! `#![feature(lazy_type_alias)]` and `#![feature(type_alias_impl_trait)]`. //! //! Since a free alias is never ambiguous, this just computes the `type_of` of @@ -17,10 +17,10 @@ where { pub(super) fn normalize_free_alias( &mut self, - goal: Goal>, + goal: Goal>, ) -> QueryResultOrRerunNonErased { let cx = self.cx(); - let free_alias = goal.predicate.alias; + let free_alias = goal.predicate.projection_term; // Check where clauses self.add_goals( @@ -41,15 +41,17 @@ where .skip_norm_wip() .into(), ty::AliasTermKind::FreeConst { .. } => { - return self.evaluate_const_and_instantiate_normalizes_to_term( - goal, + return self.evaluate_const_and_instantiate_projection_term( + goal.param_env, + free_alias, + goal.predicate.term, free_alias.expect_ct(), ); } kind => panic!("expected free alias, found {kind:?}"), }; - 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/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 16a86cc44ccf9..6183bda38a916 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 @@ -1,4 +1,4 @@ -//! Computes a normalizes-to (projection) goal for inherent associated types, +//! Computes a projection goal for inherent associated types, //! `#![feature(inherent_associated_type)]`. Since HIR ty lowering already determines //! which impl the IAT is being projected from, we just: //! 1. instantiate generic parameters, @@ -18,11 +18,11 @@ where { pub(super) fn normalize_inherent_associated_term( &mut self, - goal: Goal>, + goal: Goal>, def_id: I::InherentAssocTermId, ) -> QueryResultOrRerunNonErased { let cx = self.cx(); - let inherent = goal.predicate.alias; + let inherent = goal.predicate.projection_term; let impl_def_id = cx.inherent_alias_term_parent(def_id); let impl_args = self.fresh_args_for_item(impl_def_id.into()); @@ -74,7 +74,7 @@ where } kind => panic!("expected inherent alias, found {kind:?}"), }; - 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/project_goals/mod.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs new file mode 100644 index 0000000000000..aebfc967d39b8 --- /dev/null +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs @@ -0,0 +1,98 @@ +mod anon_const; +mod free_alias; +mod inherent; +mod opaque_types; + +use rustc_type_ir::search_graph::IncreaseDepthForNested; +use rustc_type_ir::solve::QueryResultOrRerunNonErased; +use rustc_type_ir::{self as ty, Interner, ProjectionPredicate}; +use tracing::{instrument, trace}; + +use crate::delegate::SolverDelegate; +use crate::solve::{ + Certainty, EvalCtxt, Goal, GoalEvaluation, GoalSource, NestedNormalizationGoals, +}; + +impl EvalCtxt<'_, D> +where + D: SolverDelegate, + I: Interner, +{ + #[instrument(level = "trace", skip(self), ret)] + pub(super) fn compute_projection_goal( + &mut self, + goal: Goal>, + ) -> QueryResultOrRerunNonErased { + match goal.predicate.projection_term.kind { + ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } => { + let ty::ProjectionPredicate { projection_term: alias, term } = goal.predicate; + let unconstrained_term = self.next_term_infer_of_kind(term); + let normalizes_to = + goal.with(self.cx(), ty::NormalizesTo { alias, term: unconstrained_term }); + + let ( + NestedNormalizationGoals(nested_goals), + GoalEvaluation { goal: _, certainty, stalled_on: _, has_changed: _ }, + ) = self.evaluate_goal_raw( + GoalSource::TypeRelating, + normalizes_to, + None, + IncreaseDepthForNested::No, + )?; + + trace!(?nested_goals); + + // Normalize alias types in rhs. This is done in `EvalCtxt::add_goal` for nested + // goals, but we might be evaluating the root goal. + let term = + self.replace_alias_with_infer(term, GoalSource::TypeRelating, goal.param_env); + + // Add a `make_canonical_response` probe step so that we treat this as + // a candidate, even if `try_evaluate_added_goals` bails due to an error. + // It's `Certainty::AMBIGUOUS` because this candidate is not "finished", + // since equating the normalized terms will lead to additional constraints. + self.inspect.make_canonical_response(Certainty::AMBIGUOUS); + + // Apply the constraints. + self.try_evaluate_added_goals()?; + + // 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, term, unconstrained_term)?; + + // Add the nested goals from normalization to our own nested goals. + for (s, g) in nested_goals { + self.add_goal(s, g); + } + + self.evaluate_added_goals_and_make_canonical_response(certainty) + } + + ty::AliasTermKind::InherentTy { def_id } => { + self.normalize_inherent_associated_term(goal, def_id.into()) + } + ty::AliasTermKind::InherentConst { def_id } => { + self.normalize_inherent_associated_term(goal, def_id.into()) + } + ty::AliasTermKind::OpaqueTy { def_id } => self.normalize_opaque_type(goal, def_id), + ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } => { + self.normalize_free_alias(goal).map_err(Into::into) + } + ty::AliasTermKind::AnonConst { def_id } => { + self.normalize_anon_const(goal, def_id).map_err(Into::into) + } + } + } +} 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 90% 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 ddac4faeb49d8..c7073f8b7cf60 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 @@ -1,4 +1,4 @@ -//! Computes a normalizes-to (projection) goal for opaque types. This goal +//! Computes a projection goal for opaque types. This goal //! behaves differently depending on the current `TypingMode`. use rustc_type_ir::inherent::*; @@ -16,11 +16,11 @@ where #[tracing::instrument(skip(self))] pub(super) fn normalize_opaque_type( &mut self, - goal: Goal>, + goal: Goal>, def_id: I::OpaqueTyId, ) -> QueryResultOrRerunNonErased { 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() { @@ -50,7 +50,12 @@ where .filter(|&def_id| defining_opaque_types.contains(&def_id.into())) 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, + opaque_ty, + ty::Invariant, + goal.predicate.term, + )?; return self .evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into); @@ -120,7 +125,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, + opaque_ty, + ty::Invariant, + goal.predicate.term, + )?; return self .evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into); @@ -167,7 +177,12 @@ where } // Always treat the opaque type as rigid. - self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + self.relate_rigid_alias_non_alias( + goal.param_env, + opaque_ty, + ty::Invariant, + goal.predicate.term, + )?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index f78bc3e8b4884..f632a3be3c235 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -733,7 +733,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ty::PredicateKind::Ambiguous | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature { .. }) | ty::PredicateKind::NormalizesTo { .. } - | ty::PredicateKind::AliasRelate { .. } + | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => { span_bug!( span, @@ -1745,6 +1745,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { else { return None; }; + if !proj.projection_term.kind.is_trait_projection() { + return None; + } let trait_ref = self.enter_forall_and_leak_universe( predicate.kind().rebind(proj.projection_term.trait_ref(self.tcx)), @@ -1817,6 +1820,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expected_ty: ty::Term<'tcx>, long_ty_path: &mut Option, ) -> Option<(String, Span, Option)> { + if !projection_term.kind.is_trait_projection() { + return None; + } + let trait_def_id = projection_term.trait_def_id(self.tcx); let self_ty = projection_term.self_ty(); 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 1ba0bb5f776ba..4ad4eb0fd74a4 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -54,9 +54,6 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( expected_ty, }) } - ty::PredicateKind::NormalizesTo(..) => { - FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) - } ty::PredicateKind::AliasRelate(_, _, _) => { FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) } @@ -79,7 +76,7 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( | ty::PredicateKind::Ambiguous => { FulfillmentErrorCode::Select(SelectionError::Unimplemented) } - ty::PredicateKind::ConstEquate(..) => { + ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::NormalizesTo(..) => { bug!("unexpected goal: {obligation:?}") } }; @@ -307,13 +304,10 @@ impl<'tcx> BestObligation<'tcx> { ) -> ControlFlow> { assert!(!self.consider_ambiguities); let tcx = goal.infcx().tcx; - if let ty::Alias(..) = self_ty.kind() { + if let ty::Alias(alias) = *self_ty.kind() { 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::ProjectionPredicate { projection_term: alias.into(), term: infer_term.into() }; let obligation = Obligation::new(tcx, self.obligation.cause.clone(), goal.goal().param_env, pred); self.with_derived_obligation(obligation, |this| { @@ -401,12 +395,11 @@ impl<'tcx> BestObligation<'tcx> { Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))) => { self.detect_error_in_self_ty_normalization(goal, pred.self_ty())?; } - Some(ty::PredicateKind::NormalizesTo(pred)) - if let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = pred.alias.kind => + Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred))) + if pred.projection_term.kind.is_trait_projection() => { - self.detect_error_in_self_ty_normalization(goal, pred.alias.self_ty())?; - self.detect_non_well_formed_assoc_item(goal, pred.alias)?; + self.detect_error_in_self_ty_normalization(goal, pred.projection_term.self_ty())?; + self.detect_non_well_formed_assoc_item(goal, pred.projection_term)?; } Some(_) | None => {} } @@ -468,15 +461,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_pred)) => { ChildMode::Host(pred.kind().rebind(host_pred)) } - ty::PredicateKind::NormalizesTo(normalizes_to) - if matches!( - normalizes_to.alias.kind, - ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } - ) => + ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection)) + if projection.projection_term.kind.is_trait_projection() => { ChildMode::Trait(pred.kind().rebind(ty::TraitPredicate { - trait_ref: normalizes_to.alias.trait_ref(tcx), + trait_ref: projection.projection_term.trait_ref(tcx), polarity: ty::PredicatePolarity::Positive, })) } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index ad66078025bc4..ba57d8d6df6fe 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -12,9 +12,7 @@ use std::assert_matches; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::Obligation; use rustc_macros::extension; -use rustc_middle::traits::ObligationCause; use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult}; use rustc_middle::ty::{TyCtxt, VisitorResult, try_visit}; use rustc_middle::{bug, ty}; @@ -25,7 +23,6 @@ use rustc_span::Span; use tracing::instrument; use crate::solve::delegate::SolverDelegate; -use crate::traits::ObligationCtxt; pub struct InspectConfig { pub max_depth: usize, @@ -38,55 +35,9 @@ pub struct InspectGoal<'a, 'tcx> { goal: Goal<'tcx, ty::Predicate<'tcx>>, result: Result, final_revision: &'tcx inspect::Probe>, - normalizes_to_term_hack: Option>, source: GoalSource, } -/// The expected term of a `NormalizesTo` goal gets replaced -/// with an unconstrained inference variable when computing -/// `NormalizesTo` goals and we return the nested goals to the -/// caller, who also equates the actual term with the expected. -/// -/// This is an implementation detail of the trait solver and -/// not something we want to leak to users. We therefore -/// treat `NormalizesTo` goals as if they apply the expected -/// type at the end of each candidate. -#[derive(Copy, Clone)] -struct NormalizesToTermHack<'tcx> { - term: ty::Term<'tcx>, - unconstrained_term: ty::Term<'tcx>, -} - -impl<'tcx> NormalizesToTermHack<'tcx> { - /// Relate the `term` with the new `unconstrained_term` created - /// when computing the proof tree for this `NormalizesTo` goals. - /// This handles nested obligations. - fn constrain_and( - &self, - infcx: &InferCtxt<'tcx>, - span: Span, - param_env: ty::ParamEnv<'tcx>, - f: impl FnOnce(&ObligationCtxt<'_, 'tcx>), - ) -> Result { - let ocx = ObligationCtxt::new(infcx); - ocx.eq( - &ObligationCause::dummy_with_span(span), - param_env, - self.term, - self.unconstrained_term, - )?; - f(&ocx); - let errors = ocx.evaluate_obligations_error_on_ambiguity(); - if errors.is_empty() { - Ok(Certainty::Yes) - } else if errors.iter().all(|e| !e.is_true_error()) { - Ok(Certainty::AMBIGUOUS) - } else { - Err(NoSolution) - } - } -} - pub struct InspectCandidate<'a, 'tcx> { goal: &'a InspectGoal<'a, 'tcx>, kind: inspect::ProbeKind>, @@ -162,13 +113,6 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let () = instantiate_canonical_state(infcx, span, param_env, &mut orig_values, self.final_state); - if let Some(term_hack) = &self.goal.normalizes_to_term_hack { - // FIXME: We ignore the expected term of `NormalizesTo` goals - // when computing the result of its candidates. This is - // scuffed. - let _ = term_hack.constrain_and(infcx, span, param_env, |_| {}); - } - instantiated_goals .into_iter() .map(|(source, goal)| self.instantiate_proof_tree_for_nested_goal(source, goal, span)) @@ -207,12 +151,6 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { self.final_state, ); - // No reason we couldn't support this, but we don't need to for select. - assert!( - self.goal.normalizes_to_term_hack.is_none(), - "cannot use `instantiate_impl_args` with a `NormalizesTo` goal" - ); - return eager_resolve_vars(infcx, impl_args); } inspect::ProbeStep::AddGoal(..) => {} @@ -232,49 +170,9 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { ) -> InspectGoal<'a, 'tcx> { let infcx = self.goal.infcx; match goal.predicate.kind().no_bound_vars() { - Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { - let unconstrained_term = infcx.next_term_var_of_kind(term, span); - let goal = - goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); - // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the - // expected term. This means that candidates which only fail due to nested goals - // and which normalize to a different term then the final result could ICE: when - // building their proof tree, the expected term was unconstrained, but when - // instantiating the candidate it is already constrained to the result of another - // candidate. - let normalizes_to_term_hack = NormalizesToTermHack { term, unconstrained_term }; - let (proof_tree, nested_goals_result) = infcx.probe(|_| { - // Here, if we have any nested goals, then we make sure to apply them - // considering the constrained RHS, and pass the resulting certainty to - // `InspectGoal::new` so that the goal has the right result (and maintains - // the impression that we don't do this normalizes-to infer hack at all). - let (nested, proof_tree) = infcx.evaluate_root_goal_for_proof_tree(goal, span); - let nested_goals_result = nested.and_then(|nested| { - normalizes_to_term_hack.constrain_and( - infcx, - span, - proof_tree.uncanonicalized_goal.param_env, - |ocx| { - ocx.register_obligations(nested.0.into_iter().map(|(_, goal)| { - Obligation::new( - infcx.tcx, - ObligationCause::dummy_with_span(span), - goal.param_env, - goal.predicate, - ) - })); - }, - ) - }); - (proof_tree, nested_goals_result) - }); - InspectGoal::new( - infcx, - self.goal.depth + 1, - proof_tree, - Some((normalizes_to_term_hack, nested_goals_result)), - source, - ) + Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { .. })) => { + // We don't handle `NormalizesTo` as a nested goal + unreachable!() } _ => { // We're using a probe here as evaluating a goal could constrain @@ -284,7 +182,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { // from the chosen candidate. let proof_tree = infcx.probe(|_| infcx.evaluate_root_goal_for_proof_tree(goal, span).1); - InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source) + InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, source) } } } @@ -415,10 +313,6 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, depth: usize, root: inspect::GoalEvaluation>, - term_hack_and_nested_certainty: Option<( - NormalizesToTermHack<'tcx>, - Result, - )>, source: GoalSource, ) -> Self { let infcx = <&SolverDelegate<'tcx>>::from(infcx); @@ -427,11 +321,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { root; // If there's a normalizes-to goal, AND the evaluation result with the result of // constraining the normalizes-to RHS and computing the nested goals. - let result = result.and_then(|ok| { - let nested_goals_certainty = - term_hack_and_nested_certainty.map_or(Ok(Certainty::Yes), |(_, c)| c)?; - Ok(ok.value.certainty.and(nested_goals_certainty)) - }); + let result = result.map(|ok| ok.value.certainty); InspectGoal { infcx, @@ -440,7 +330,6 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { goal: eager_resolve_vars(infcx, uncanonicalized_goal), result, final_revision, - normalizes_to_term_hack: term_hack_and_nested_certainty.map(|(n, _)| n), source, } } @@ -490,6 +379,6 @@ impl<'tcx> InferCtxt<'tcx> { ) -> V::Result { let (_, proof_tree) = <&SolverDelegate<'tcx>>::from(self) .evaluate_root_goal_for_proof_tree(goal, visitor.span()); - visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None, GoalSource::Misc)) + visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, GoalSource::Misc)) } } diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 97b460fe347d8..3bbb175c08555 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -46,12 +46,10 @@ where let mut folder = NormalizationFolder::new(infcx, universes.clone(), Default::default(), |alias_term| { let delegate = <&SolverDelegate<'tcx>>::from(infcx); - let infer_term = delegate.next_term_var_of_kind(alias_term, at.cause.span); - let predicate = ty::PredicateKind::AliasRelate( - alias_term, - infer_term, - ty::AliasRelationDirection::Equate, - ); + let infer_term = + delegate.next_term_var_of_kind(alias_term.to_term(infcx.tcx), at.cause.span); + let predicate = + ty::ProjectionPredicate { projection_term: alias_term, term: infer_term }; let goal = Goal::new(infcx.tcx, at.param_env, predicate); let result = delegate.evaluate_root_goal(goal, at.cause.span, None)?; let normalized = infcx.resolve_vars_if_possible(infer_term); @@ -84,18 +82,15 @@ struct ReplaceAliasWithInfer<'me, 'tcx> { } impl<'me, 'tcx> ReplaceAliasWithInfer<'me, 'tcx> { - fn term_to_infer(&mut self, alias_term: ty::Term<'tcx>) -> ty::Term<'tcx> { + fn term_to_infer(&mut self, alias_term: ty::AliasTerm<'tcx>) -> ty::Term<'tcx> { let infcx = self.at.infcx; - let infer_term = infcx.next_term_var_of_kind(alias_term, self.at.cause.span); + let infer_term = + infcx.next_term_var_of_kind(alias_term.to_term(infcx.tcx), self.at.cause.span); let obligation = Obligation::new( infcx.tcx, self.at.cause.clone(), self.at.param_env, - ty::PredicateKind::AliasRelate( - alias_term, - infer_term, - ty::AliasRelationDirection::Equate, - ), + ty::ProjectionPredicate { projection_term: alias_term, term: infer_term }, ); self.obligations.push(obligation); infer_term @@ -123,15 +118,15 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { } let ty = ty.super_fold_with(self); - let ty::Alias(..) = *ty.kind() else { return ty }; + let ty::Alias(alias) = *ty.kind() else { return ty }; if ty.has_escaping_bound_vars() { let (replaced, ..) = - BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, ty); + BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, alias); let _ = self.term_to_infer(replaced.into()); ty } else { - self.term_to_infer(ty.into()).expect_type() + self.term_to_infer(alias.into()).expect_type() } } @@ -141,15 +136,15 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { } let ct = ct.super_fold_with(self); - let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct }; + let ty::ConstKind::Unevaluated(uc) = ct.kind() else { return ct }; if ct.has_escaping_bound_vars() { let (replaced, ..) = - BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, ct); + BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, uc); let _ = self.term_to_infer(replaced.into()); ct } else { - self.term_to_infer(ct.into()).expect_const() + self.term_to_infer(uc.into()).expect_const() } } } diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index 03edfeb06d8c4..6c1236bec8320 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -41,20 +41,20 @@ impl<'tcx> At<'_, 'tcx> { if self.infcx.next_trait_solver() { let term = term.skip_normalization(); - 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); - // We simply emit an `alias-eq` goal here, since that will take care of + // We simply emit an `Projection` goal here, since that will take care of // normalizing the LHS of the projection until it is a rigid projection // (or a not-yet-defined opaque in scope). let obligation = Obligation::new( self.infcx.tcx, self.cause.clone(), self.param_env, - ty::PredicateKind::AliasRelate(term, new_infer, ty::AliasRelationDirection::Equate), + ty::ProjectionPredicate { projection_term: alias, term: new_infer }, ); fulfill_cx.register_predicate_obligation(self.infcx, obligation); diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index e0fe608198921..bffb6aa8060ed 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -472,6 +472,7 @@ pub trait Predicate>: + UpcastFrom> + UpcastFrom>> + UpcastFrom> + + UpcastFrom> + UpcastFrom> + UpcastFrom> + IntoKind>> @@ -479,14 +480,6 @@ pub trait Predicate>: { fn as_clause(self) -> Option; - fn as_normalizes_to(self) -> Option>> { - let kind = self.kind(); - match kind.skip_binder() { - ty::PredicateKind::NormalizesTo(pred) => Some(kind.rebind(pred)), - _ => None, - } - } - fn allow_normalization(self) -> bool { match self.kind().skip_binder() { PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) => { diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 8de64762c30b5..1e6668801934f 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -633,6 +633,18 @@ impl AliasTermKind { AliasTermKind::InherentConst { def_id } => def_id.into(), } } + + pub fn is_trait_projection(self) -> bool { + match self { + AliasTermKind::ProjectionTy { .. } | AliasTermKind::ProjectionConst { .. } => true, + AliasTermKind::InherentTy { .. } + | AliasTermKind::OpaqueTy { .. } + | AliasTermKind::FreeTy { .. } + | AliasTermKind::AnonConst { .. } + | AliasTermKind::FreeConst { .. } + | AliasTermKind::InherentConst { .. } => false, + } + } } impl From> for AliasTermKind { diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 3a962b3832aa3..0a9b30f84719b 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -262,6 +262,12 @@ impl CandidateHeadUsages { } } +#[derive(Debug, Clone, Copy)] +pub enum IncreaseDepthForNested { + Yes, + No, +} + #[derive(Debug, Clone, Copy)] struct AvailableDepth(usize); impl AvailableDepth { @@ -283,7 +289,10 @@ impl AvailableDepth { Some(if last.encountered_overflow { AvailableDepth(last.available_depth.0 / D::DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW) } else { - AvailableDepth(last.available_depth.0 - 1) + match last.increase_depth_for_nested { + IncreaseDepthForNested::Yes => AvailableDepth(last.available_depth.0 - 1), + IncreaseDepthForNested::No => last.available_depth, + } }) } else { Some(root_depth) @@ -625,7 +634,11 @@ impl, X: Cx> SearchGraph { context: UpdateParentGoalCtxt<'_, X>, ) { if let Some((parent_index, parent)) = stack.last_mut_with_index() { - parent.required_depth = parent.required_depth.max(required_depth_for_nested + 1); + parent.required_depth = + parent.required_depth.max(match parent.increase_depth_for_nested { + IncreaseDepthForNested::Yes => required_depth_for_nested + 1, + IncreaseDepthForNested::No => required_depth_for_nested, + }); parent.encountered_overflow |= encountered_overflow; for (head_index, head) in heads { @@ -741,6 +754,7 @@ impl, X: Cx> SearchGraph { available_depth, provisional_result: None, required_depth: 0, + increase_depth_for_nested: IncreaseDepthForNested::Yes, heads: Default::default(), encountered_overflow: false, usages: None, @@ -761,6 +775,7 @@ impl, X: Cx> SearchGraph { cx: X, input: X::Input, step_kind_from_parent: PathKind, + increase_depth_for_nested: IncreaseDepthForNested, inspect: &mut D::ProofTreeBuilder, ) -> X::Result { let Some(available_depth) = @@ -817,6 +832,7 @@ impl, X: Cx> SearchGraph { available_depth, provisional_result: None, required_depth: 0, + increase_depth_for_nested, heads: Default::default(), encountered_overflow: false, usages: None, @@ -1408,6 +1424,7 @@ impl, X: Cx> SearchGraph { // We can keep these goals from previous iterations as they are only // ever read after finalizing this evaluation. required_depth: stack_entry.required_depth, + increase_depth_for_nested: stack_entry.increase_depth_for_nested, heads: stack_entry.heads, nested_goals: stack_entry.nested_goals, // We reset these two fields when rerunning this goal. We could diff --git a/compiler/rustc_type_ir/src/search_graph/stack.rs b/compiler/rustc_type_ir/src/search_graph/stack.rs index 8348666be412d..877ef673acc98 100644 --- a/compiler/rustc_type_ir/src/search_graph/stack.rs +++ b/compiler/rustc_type_ir/src/search_graph/stack.rs @@ -4,7 +4,8 @@ use derive_where::derive_where; use rustc_index::IndexVec; use crate::search_graph::{ - AvailableDepth, CandidateHeadUsages, Cx, CycleHeads, HeadUsages, NestedGoals, PathKind, + AvailableDepth, CandidateHeadUsages, Cx, CycleHeads, HeadUsages, IncreaseDepthForNested, + NestedGoals, PathKind, }; rustc_index::newtype_index! { @@ -31,6 +32,17 @@ pub(super) struct StackEntry { /// The maximum depth required while evaluating this goal. pub required_depth: usize, + /// Whether evaluating nested goals of a given goal should increase the depth. + /// + /// Normally, it should be `Yes`, but among rustc's predicate goals, `normalizes-to` + /// goals are exceptions. They act like functions that used for normalizing associated + /// terms while evaluating projection goals and since their expected terms are always fully + /// unconstrained intentionally, they often return ambiguous nested goals to the caller's + /// context. As these nested goals are evaluated again in the caller's context, we don't + /// want to increase depths when they are evaluated as nested goals for `normalizes-to` + /// goals, otherwise we will encounter recursion limit overflows more often. + pub increase_depth_for_nested: IncreaseDepthForNested, + /// Starts out as `None` and gets set when rerunning this /// goal in case we encounter a cycle. pub provisional_result: Option, diff --git a/tests/ui/associated-inherent-types/normalization-overflow.next.stderr b/tests/ui/associated-inherent-types/normalization-overflow.next.stderr index 5f0939b9f7763..376a071fdb248 100644 --- a/tests/ui/associated-inherent-types/normalization-overflow.next.stderr +++ b/tests/ui/associated-inherent-types/normalization-overflow.next.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `T::This normalizes-to _` +error[E0271]: type mismatch resolving `_ == T::This` --> $DIR/normalization-overflow.rs:14:5 | LL | type This = Self::This; diff --git a/tests/ui/associated-inherent-types/normalization-overflow.rs b/tests/ui/associated-inherent-types/normalization-overflow.rs index c5505578f4f00..da3e83c2c5997 100644 --- a/tests/ui/associated-inherent-types/normalization-overflow.rs +++ b/tests/ui/associated-inherent-types/normalization-overflow.rs @@ -13,7 +13,7 @@ struct T; impl T { type This = Self::This; //[current]~^ ERROR: overflow evaluating associated type `T::This` - //[next]~^^ ERROR: type mismatch resolving `T::This normalizes-to _` + //[next]~^^ ERROR: type mismatch resolving `_ == T::This` } fn main() {} diff --git a/tests/ui/auto-traits/assoc-ty.next.stderr b/tests/ui/auto-traits/assoc-ty.next.stderr index 19621064aa429..ea04e84487b1a 100644 --- a/tests/ui/auto-traits/assoc-ty.next.stderr +++ b/tests/ui/auto-traits/assoc-ty.next.stderr @@ -22,21 +22,13 @@ LL | | } = help: add `#![feature(auto_traits)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0271]: type mismatch resolving `<() as Trait>::Output normalizes-to _` +error[E0271]: type mismatch resolving `<() as Trait>::Output == _` --> $DIR/assoc-ty.rs:17:12 | LL | let _: <() as Trait>::Output = (); | ^^^^^^^^^^^^^^^^^^^^^ types differ -error[E0271]: type mismatch resolving `<() as Trait>::Output normalizes-to _` - --> $DIR/assoc-ty.rs:17:12 - | -LL | let _: <() as Trait>::Output = (); - | ^^^^^^^^^^^^^^^^^^^^^ types differ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0271, E0380, E0658. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/auto-traits/assoc-ty.rs b/tests/ui/auto-traits/assoc-ty.rs index 98a86d9a75407..e1a50c06f4968 100644 --- a/tests/ui/auto-traits/assoc-ty.rs +++ b/tests/ui/auto-traits/assoc-ty.rs @@ -17,6 +17,5 @@ fn main() { let _: <() as Trait>::Output = (); //[current]~^ ERROR mismatched types //[current]~| HELP consider constraining the associated type `<() as Trait>::Output` to `()` or calling a method that returns `<() as Trait>::Output` - //[next]~^^^ ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _` - //[next]~| ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _` + //[next]~^^^ ERROR type mismatch resolving `<() as Trait>::Output == _` } 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 04c1aaa192ee3..7c5cd982aefc7 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 == T` --> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:5 | LL | foo::, U>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize ` as Object>::Output` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy ` as Object>::Output == 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..0b66a6e783032 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 == 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 38fb75483f3b3..1dac3ecea2687 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -14,13 +14,6 @@ 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` - --> $DIR/associated-type.rs:45:5 - | -LL | foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0284. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs index d56ccc5b3532d..cb3a6c4f7e8cb 100644 --- a/tests/ui/coherence/occurs-check/associated-type.rs +++ b/tests/ui/coherence/occurs-check/associated-type.rs @@ -43,5 +43,4 @@ fn foo, U>(x: T::Assoc) -> T::Assoc { fn main() { foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); - //[next]~^ ERROR: cannot normalize } diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr index f609dcab752af..efe7265a924c4 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr @@ -14,11 +14,14 @@ help: consider giving this pattern a type, where the value of const parameter `N LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = free(); | +++++++++++++ -error[E0271]: type mismatch resolving `10 == 2` +error[E0271]: type mismatch resolving `FREE<10> == 2` --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:35:45 | LL | let (mut arr, mut arr_with_weird_len) = free(); - | ^^^^^^ types differ + | ^^^^^^ expected `2`, found `10` + | + = note: expected constant `2` + found constant `10` error[E0284]: type annotations needed for `([(); _], [(); 10])` --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:46:9 @@ -36,11 +39,14 @@ help: consider giving this pattern a type, where the value of const parameter `N LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = proj(); | +++++++++++++ -error[E0271]: type mismatch resolving `10 == 2` +error[E0271]: type mismatch resolving `::PROJ<10> == 2` --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:52:45 | LL | let (mut arr, mut arr_with_weird_len) = proj(); - | ^^^^^^ types differ + | ^^^^^^ expected `2`, found `10` + | + = note: expected constant `2` + found constant `10` error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs index 72952940b1c12..902be2d8b1a8f 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs @@ -33,7 +33,7 @@ fn test_free() { fn test_free_mismatch() { let (mut arr, mut arr_with_weird_len) = free(); - //[next]~^ ERROR type mismatch resolving `10 == 2` + //[next]~^ ERROR type mismatch resolving `FREE<10> == 2` arr_with_weird_len = [(); 2]; arr = [(); 10]; } @@ -50,7 +50,7 @@ fn test_proj() { fn test_proj_mismatch() { let (mut arr, mut arr_with_weird_len) = proj(); - //[next]~^ ERROR type mismatch resolving `10 == 2` + //[next]~^ ERROR type mismatch resolving `::PROJ<10> == 2` arr_with_weird_len = [(); 2]; arr = [(); 10]; } 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/const-generics/mgca/projection-const-recursive.rs b/tests/ui/const-generics/mgca/projection-const-recursive.rs index c9b5039b5fd0b..330a182549a6c 100644 --- a/tests/ui/const-generics/mgca/projection-const-recursive.rs +++ b/tests/ui/const-generics/mgca/projection-const-recursive.rs @@ -10,7 +10,7 @@ trait Trait { impl Trait for () { type const A: () = <() as Trait>::A; - //~^ ERROR type mismatch resolving `<() as Trait>::A normalizes-to _` + //~^ ERROR type mismatch resolving `<() as Trait>::A == _` //~| ERROR the constant `<() as Trait>::A` is not of type `()` } diff --git a/tests/ui/const-generics/mgca/projection-const-recursive.stderr b/tests/ui/const-generics/mgca/projection-const-recursive.stderr index d9c60102c3184..8f6ca9e4b7d24 100644 --- a/tests/ui/const-generics/mgca/projection-const-recursive.stderr +++ b/tests/ui/const-generics/mgca/projection-const-recursive.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<() as Trait>::A normalizes-to _` +error[E0271]: type mismatch resolving `<() as Trait>::A == _` --> $DIR/projection-const-recursive.rs:12:5 | LL | type const A: () = <() as Trait>::A; diff --git a/tests/ui/const-generics/type-const-ice-issue-151631.rs b/tests/ui/const-generics/type-const-ice-issue-151631.rs index 53c6d0c6dd6d4..c20adda1c6366 100644 --- a/tests/ui/const-generics/type-const-ice-issue-151631.rs +++ b/tests/ui/const-generics/type-const-ice-issue-151631.rs @@ -14,5 +14,5 @@ impl Trait for () { //~ ERROR: the trait bound `(): SuperTrait` is not satisfied fn check(_: impl Trait) {} fn main() { - check(()); //~ ERROR: the trait bound `(): SuperTrait` is not satisfied + check(()); //~ ERROR: type mismatch resolving `<() as Trait>::K == 0` } diff --git a/tests/ui/const-generics/type-const-ice-issue-151631.stderr b/tests/ui/const-generics/type-const-ice-issue-151631.stderr index 6f287293e27cf..1c4f7448c8580 100644 --- a/tests/ui/const-generics/type-const-ice-issue-151631.stderr +++ b/tests/ui/const-generics/type-const-ice-issue-151631.stderr @@ -15,23 +15,23 @@ note: required by a bound in `Trait` LL | trait Trait: SuperTrait { | ^^^^^^^^^^ required by this bound in `Trait` -error[E0277]: the trait bound `(): SuperTrait` is not satisfied - --> $DIR/type-const-ice-issue-151631.rs:17:5 +error[E0271]: type mismatch resolving `<() as Trait>::K == 0` + --> $DIR/type-const-ice-issue-151631.rs:17:11 | LL | check(()); - | ^^^^^^^^^ the trait `SuperTrait` is not implemented for `()` + | ----- ^^ expected `0`, found `1` + | | + | required by a bound introduced by this call | -help: this trait has no implementations, consider adding one - --> $DIR/type-const-ice-issue-151631.rs:6:1 - | -LL | trait SuperTrait {} - | ^^^^^^^^^^^^^^^^ -note: required by a bound in `Trait` - --> $DIR/type-const-ice-issue-151631.rs:7:14 + = note: expected constant `0` + found constant `1` +note: required by a bound in `check` + --> $DIR/type-const-ice-issue-151631.rs:14:24 | -LL | trait Trait: SuperTrait { - | ^^^^^^^^^^ required by this bound in `Trait` +LL | fn check(_: impl Trait) {} + | ^^^^^ required by this bound in `check` error: aborting due to 2 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/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr index 31d74d1c022a1..1f14d2a80d0f3 100644 --- a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr +++ b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr @@ -1,8 +1,10 @@ -error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to >::Assoc` +error[E0284]: type annotations needed --> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:50 | LL | let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::(); - | ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to >::Assoc` + | ^^^^^^^^^^ cannot infer type + | + = note: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc == >::Assoc` error: aborting due to 1 previous error 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 3398ed2120349..c4cb190608160 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,11 +25,17 @@ 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 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `::LineStreamFut<'a, Repr> == ()` + | +note: types differ + --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:36 + | +LL | type LineStreamFut<'a, Repr> = impl Future>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors 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 4c3ec862675aa..40dc609550cc1 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,7 +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 _` [E0271] + //[next]~^^^ ERROR type mismatch resolving `::LineStreamFut<'a, Repr> == ()` } pub fn main() {} diff --git a/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature_new.stderr b/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature_new.stderr index 1d6ace580951b..f831df8fbd92e 100644 --- a/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature_new.stderr +++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature_new.stderr @@ -1,16 +1,16 @@ -error[E0271]: type mismatch resolving `X3 normalizes-to _` +error[E0271]: type mismatch resolving `_ == X1` --> $DIR/infinite-type-alias-mutual-recursion.rs:12:1 | LL | type X1 = X2; | ^^^^^^^ types differ -error[E0271]: type mismatch resolving `X1 normalizes-to _` +error[E0271]: type mismatch resolving `_ == X2` --> $DIR/infinite-type-alias-mutual-recursion.rs:16:1 | LL | type X2 = X3; | ^^^^^^^ types differ -error[E0271]: type mismatch resolving `X2 normalizes-to _` +error[E0271]: type mismatch resolving `_ == X3` --> $DIR/infinite-type-alias-mutual-recursion.rs:19:1 | LL | type X3 = X1; diff --git a/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs b/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs index 24e1318ca3d7d..553d196891959 100644 --- a/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs +++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs @@ -12,12 +12,12 @@ type X1 = X2; //[gated_old,gated_new]~^ ERROR cycle detected when expanding type alias `X1` //[feature_old]~^^ ERROR: overflow normalizing the type alias `X2` -//[feature_new]~^^^ ERROR: type mismatch resolving `X3 normalizes-to _` +//[feature_new]~^^^ ERROR: type mismatch resolving `_ == X1` type X2 = X3; //[feature_old]~^ ERROR: overflow normalizing the type alias `X3` -//[feature_new]~^^ ERROR: type mismatch resolving `X1 normalizes-to _` +//[feature_new]~^^ ERROR: type mismatch resolving `_ == X2` type X3 = X1; //[feature_old]~^ ERROR: overflow normalizing the type alias `X1` -//[feature_new]~^^ ERROR: type mismatch resolving `X2 normalizes-to _` +//[feature_new]~^^ ERROR: type mismatch resolving `_ == X3` fn main() {} diff --git a/tests/ui/issues/issue-33941.next.stderr b/tests/ui/issues/issue-33941.next.stderr index a5a6e51545a58..d653bbd327427 100644 --- a/tests/ui/issues/issue-33941.next.stderr +++ b/tests/ui/issues/issue-33941.next.stderr @@ -6,6 +6,13 @@ LL | for _ in HashMap::new().iter().cloned() {} | = note: expected reference `&_` found tuple `(&_, &_)` +note: the method call chain might not have had the expected associated types + --> $DIR/issue-33941.rs:9:29 + | +LL | for _ in HashMap::new().iter().cloned() {} + | -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here + | | + | this expression has type `HashMap<_, _>` note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL 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..863bc24afd39d 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr @@ -1,16 +1,16 @@ -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 {} diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs index b4a347cb098ca..44226f4812adb 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<(((((((...,),),),),),),)>` diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed index 06aecc21be70e..c489b6e445dda 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed @@ -6,7 +6,9 @@ fn main() { let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments //[next]~^^ ERROR: expected a `FnMut(&{integer})` closure, found + //[next]~| ERROR: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:6:29} as FnOnce<(&{integer},)>>::Output == bool` let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments //[next]~^^ ERROR: expected a `FnMut(&{integer})` closure, found + //[next]~| ERROR: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:10:29} as FnOnce<(&{integer},)>>::Output == bool` } diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.stderr index c35d70a635cbd..a6ba644f3a44a 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.stderr @@ -16,7 +16,7 @@ LL | let _ = (-10..=10).find(|x: &i32| x.signum() == 0); | + error[E0631]: type mismatch in closure arguments - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:24 + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:10:24 | LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); | ^^^^ ----------- found signature defined here diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr index 3423ce65a0c1b..412fd53baeb37 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr @@ -12,20 +12,43 @@ LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error[E0277]: expected a `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:29 +error[E0271]: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:6:29} as FnOnce<(&{integer},)>>::Output == bool` + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:6:29 + | +LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | | + | required by a bound introduced by this call + | +note: required by a bound in `find` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: expected a `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:10:29: 10:40}` + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:10:29 | LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:10:29: 10:40}` | | | required by a bound introduced by this call | - = help: the trait `for<'a> FnMut(&'a {integer})` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` + = help: the trait `for<'a> FnMut(&'a {integer})` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:10:29: 10:40}` = note: expected a closure with signature `for<'a> fn(&'a {integer})` found a closure with signature `fn(&&&i32)` note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error: aborting due to 2 previous errors +error[E0271]: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:10:29} as FnOnce<(&{integer},)>>::Output == bool` + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:10:29 + | +LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | | + | required by a bound introduced by this call + | +note: required by a bound in `find` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 4 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/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs index fbfc425860250..434b5d3d23110 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs @@ -6,7 +6,9 @@ fn main() { let _ = (-10..=10).find(|x: i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments //[next]~^^ ERROR: expected a `FnMut(&{integer})` closure, found + //[next]~| ERROR: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:6:29} as FnOnce<(&{integer},)>>::Output == bool` let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments //[next]~^^ ERROR: expected a `FnMut(&{integer})` closure, found + //[next]~| ERROR: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:10:29} as FnOnce<(&{integer},)>>::Output == bool` } diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index 6cd0b0b1aaa30..432b13d161afb 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -28,7 +28,5 @@ fn main() { let _ = identity(<() as Foo>::copy_me(&x)); //~^ ERROR: overflow evaluating the requirement `<() as Foo>::Item == String` [E0275] //~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275] - //~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275] - //~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275] 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 60e337f98d8a2..b20534f5dc584 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -18,26 +18,12 @@ 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 == _` - --> $DIR/alias-bound-unsound.rs:28:22 - | -LL | let _ = identity(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` --> $DIR/alias-bound-unsound.rs:28:43 | LL | let _ = identity(<() as Foo>::copy_me(&x)); | ^^ -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` - --> $DIR/alias-bound-unsound.rs:28:22 - | -LL | let _ = identity(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-4.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-4.next.stderr index c7d774644c2ba..f21da6f473cda 100644 --- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-4.next.stderr +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-4.next.stderr @@ -1,8 +1,10 @@ -error[E0284]: type annotations needed: cannot normalize `>::Type` +error[E0284]: type annotations needed --> $DIR/ambiguity-due-to-uniquification-4.rs:17:44 | LL | pub fn f<'a, 'b, T: Trait<'a> + Trait<'b>>(v: >::Type) {} - | ^ cannot normalize `>::Type` + | ^ cannot infer type + | + = note: cannot satisfy `>::Type == _` error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/async.fail.stderr b/tests/ui/traits/next-solver/async.fail.stderr index a76a10d20ee8b..bc89842d16a14 100644 --- a/tests/ui/traits/next-solver/async.fail.stderr +++ b/tests/ui/traits/next-solver/async.fail.stderr @@ -1,8 +1,8 @@ -error[E0271]: type mismatch resolving `() == i32` +error[E0271]: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()` --> $DIR/async.rs:12:17 | LL | needs_async(async {}); - | ----------- ^^^^^^^^ types differ + | ----------- ^^^^^^^^ expected `i32`, found `()` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/next-solver/async.rs b/tests/ui/traits/next-solver/async.rs index 34c0ed02eeb12..fded774354759 100644 --- a/tests/ui/traits/next-solver/async.rs +++ b/tests/ui/traits/next-solver/async.rs @@ -10,7 +10,7 @@ fn needs_async(_: impl Future) {} #[cfg(fail)] fn main() { needs_async(async {}); - //[fail]~^ ERROR type mismatch resolving `() == i32` + //[fail]~^ ERROR expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()` } #[cfg(pass)] 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 3dd266f09145c..ceb08281e4991 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 @@ -16,14 +16,6 @@ error[E0275]: overflow evaluating the requirement ` as Trait>::P LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0275]: overflow evaluating the requirement ` as Trait>::Proof == _` - --> $DIR/item-bound-via-impl-where-clause.rs:31:21 - | -LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0275`. 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 3ddad6557693b..2cf191669630a 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 @@ -31,6 +31,5 @@ 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 == _` - //[next]~| ERROR: overflow evaluating the requirement ` as Trait>::Proof == _` println!("{}", s); // ABC } diff --git a/tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.stderr b/tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.stderr index ff3cbdb2c7841..5f886be7b4f78 100644 --- a/tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.stderr +++ b/tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.stderr @@ -2,10 +2,15 @@ error[E0271]: type mismatch resolving ` as Trait>::Assoc == u32` --> $DIR/alias_relate_error_uses_structurally_normalize.rs:24:9 | LL | bar(foo); - | --- ^^^ expected `u32`, found `u64` + | --- ^^^ type mismatch resolving ` as Trait>::Assoc == u32` | | | required by a bound introduced by this call | +note: expected this to be `u32` + --> $DIR/alias_relate_error_uses_structurally_normalize.rs:17:18 + | +LL | type Assoc = u64; + | ^^^ note: required by a bound in `bar` --> $DIR/alias_relate_error_uses_structurally_normalize.rs:20:17 | diff --git a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs index 4185228a2586f..8463cb3f6ea1b 100644 --- a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs +++ b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs @@ -6,7 +6,9 @@ const fn with_positive [const] Fn(&'a ())>() {} const _: () = { - with_positive::<()>(); //~ ERROR expected a `Fn(&'a ())` closure, found `()` + with_positive::<()>(); + //~^ ERROR expected a `Fn(&'a ())` closure, found `()` + //~| ERROR type mismatch resolving `<() as FnOnce<(&(),)>>::Output == ()` }; fn main() {} diff --git a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr index 18f513cea6d49..8ec772a3d7fa8 100644 --- a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr +++ b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr @@ -11,6 +11,19 @@ note: required by a bound in `with_positive` LL | const fn with_positive [const] Fn(&'a ())>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_positive` -error: aborting due to 1 previous error +error[E0271]: type mismatch resolving `<() as FnOnce<(&(),)>>::Output == ()` + --> $DIR/const-host-effect-hrtb-no-ice.rs:9:21 + | +LL | with_positive::<()>(); + | ^^ types differ + | +note: required by a bound in `with_positive` + --> $DIR/const-host-effect-hrtb-no-ice.rs:6:43 + | +LL | const fn with_positive [const] Fn(&'a ())>() {} + | ^^^^^^^^^^ required by this bound in `with_positive` + +error: aborting due to 2 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/next-solver/lazy-nested-obligations-2.next.stderr b/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr index 462544b405218..ba8d29263b747 100644 --- a/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr +++ b/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr @@ -1,14 +1,30 @@ -error[E0271]: type mismatch resolving `fn(&str) == fn(&str) {f}` +error[E0271]: type mismatch resolving `::F == fn(&str) {f}` --> $DIR/lazy-nested-obligations-2.rs:20:21 | LL | let _: V = V(f); - | ^^^^ types differ + | ^^^^ type mismatch resolving `::F == fn(&str) {f}` + | +note: expected this to be `for<'a> fn(&'a str) {f}` + --> $DIR/lazy-nested-obligations-2.rs:14:14 + | +LL | type F = fn(&str); + | ^^^^^^^^ + = note: expected fn item `for<'a> fn(&'a _) {f}` + found fn pointer `for<'a> fn(&'a _)` -error[E0271]: type mismatch resolving `fn(&str) == fn(&str) {f}` +error[E0271]: type mismatch resolving `::F == fn(&str) {f}` --> $DIR/lazy-nested-obligations-2.rs:27:22 | LL | let _: E3 = E3::Var(f); - | ^^^^^^^^^^ types differ + | ^^^^^^^^^^ type mismatch resolving `::F == fn(&str) {f}` + | +note: expected this to be `for<'a> fn(&'a str) {f}` + --> $DIR/lazy-nested-obligations-2.rs:14:14 + | +LL | type F = fn(&str); + | ^^^^^^^^ + = note: expected fn item `for<'a> fn(&'a _) {f}` + found fn pointer `for<'a> fn(&'a _)` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/next-solver/more-object-bound.rs b/tests/ui/traits/next-solver/more-object-bound.rs index 1dad1903a649d..3d3fdc926f658 100644 --- a/tests/ui/traits/next-solver/more-object-bound.rs +++ b/tests/ui/traits/next-solver/more-object-bound.rs @@ -10,7 +10,7 @@ trait Trait: SuperTrait::B> {} fn transmute(x: A) -> B { foo::>(x) - //~^ ERROR type mismatch resolving `A == B` + //~^ ERROR type mismatch resolving ` as SuperTrait>::A == B` } fn foo(x: T::A) -> B diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr index 7d279ed64282b..ccbf19ae4d96c 100644 --- a/tests/ui/traits/next-solver/more-object-bound.stderr +++ b/tests/ui/traits/next-solver/more-object-bound.stderr @@ -1,9 +1,17 @@ -error[E0271]: type mismatch resolving `A == B` +error[E0271]: type mismatch resolving ` as SuperTrait>::A == B` --> $DIR/more-object-bound.rs:12:17 | +LL | fn transmute(x: A) -> B { + | - - expected type parameter + | | + | found type parameter LL | foo::>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A` | + = note: expected type parameter `B` + found type parameter `A` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters = note: required because it appears within the type `dyn Trait` note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 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 ecd86dba97994..d3effe2eb0389 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 @@ -6,16 +6,6 @@ LL | | where LL | | Self::Assoc: A, | |__________________________^ -error[E0275]: overflow evaluating the requirement `<() as A>::Assoc == _` - --> $DIR/normalize-param-env-2.rs:22:5 - | -LL | / fn f() -LL | | where -LL | | Self::Assoc: A, - | |__________________________^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0275]: overflow evaluating the requirement `<() as A>::Assoc == _` --> $DIR/normalize-param-env-2.rs:24:22 | @@ -92,7 +82,7 @@ LL | where LL | Self::Assoc: A, | ^^^^ required by this bound in `A::f` -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0275, E0283. For more information about an error, try `rustc --explain E0275`. 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..12ea1bf142ab8 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 == 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..21f3fbfeb872e 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 == i32` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17 | LL | needs_bar::(); - | ^ cannot normalize `::Assoc` + | ^ cannot satisfy `::Assoc == i32` | note: required for `T` to implement `Bar` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9 diff --git a/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.next.stderr b/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.next.stderr index d7046d2b058ba..67334e12326f3 100644 --- a/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.next.stderr +++ b/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.next.stderr @@ -1,18 +1,15 @@ -error[E0271]: type mismatch resolving `::Diverges normalizes-to _` +error[E0271]: type mismatch resolving `::Diverges == _` --> $DIR/normalize-diverging-alias-in-struct.rs:21:12 | LL | field: Box<::Diverges>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ - -error[E0271]: type mismatch resolving `::Diverges normalizes-to _` - --> $DIR/normalize-diverging-alias-in-struct.rs:21:12 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `::Diverges == _` | -LL | field: Box<::Diverges>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ +note: types differ + --> $DIR/normalize-diverging-alias-in-struct.rs:17:31 | -note: required by a bound in `Box` - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +LL | type Diverges = D::Diverges; + | ^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.rs b/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.rs index 45b2cb56c25f7..0b31bf32aa285 100644 --- a/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.rs +++ b/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.rs @@ -20,8 +20,7 @@ impl Trait for T { struct Foo { field: Box<::Diverges>, //[current]~^ ERROR: overflow evaluating the requirement `::Diverges == _` - //[next]~^^ ERROR: type mismatch resolving `::Diverges normalizes-to _` - //[next]~| ERROR: type mismatch resolving `::Diverges normalizes-to _` + //[next]~^^ ERROR: type mismatch resolving `::Diverges == _` } fn main() {} 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 8e114f546db4f..fcac02bc0a049 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,9 @@ +error[E0271]: type mismatch resolving `::Assert == _` + --> $DIR/trivial-unsized-projection-2.rs:22:12 + | +LL | const FOO: ::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ types differ + error[E0277]: the size for values of type `[()]` cannot be known at compilation time --> $DIR/trivial-unsized-projection-2.rs:22:12 | @@ -23,19 +29,13 @@ help: consider relaxing the implicit `Sized` restriction LL | type Assert: ?Sized | ++++++++ -error[E0277]: the size for values of type `[()]` cannot be known at compilation time +error[E0271]: type mismatch resolving `::Assert == _` --> $DIR/trivial-unsized-projection-2.rs:22:36 | LL | const FOO: ::Assert = todo!(); - | ^^^^^^^ doesn't have a size known at compile-time - | - = help: within `Tail`, the trait `Sized` is not implemented for `[()]` -note: required because it appears within the type `Tail` - --> $DIR/trivial-unsized-projection-2.rs:17:8 - | -LL | struct Tail([()]); - | ^^^^ + | ^^^^^^^ types differ -error: aborting due to 2 previous errors +error: aborting due to 3 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..175a2712d25b5 100644 --- a/tests/ui/traits/trivial-unsized-projection-2.rs +++ b/tests/ui/traits/trivial-unsized-projection-2.rs @@ -23,7 +23,8 @@ const FOO: ::Assert = todo!(); //[bad]~^ ERROR the size for values of type `[()]` cannot be known at compilation time //[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 == _` +//[bad_new]~| ERROR: type mismatch resolving `::Assert == _` #[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 a9ce3ba56f869..09b51b30460d0 100644 --- a/tests/ui/traits/trivial-unsized-projection.bad_new.stderr +++ b/tests/ui/traits/trivial-unsized-projection.bad_new.stderr @@ -1,3 +1,9 @@ +error[E0271]: type mismatch resolving `<[()] as Bad>::Assert == _` + --> $DIR/trivial-unsized-projection.rs:20:12 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ types differ + error[E0277]: the size for values of type `[()]` cannot be known at compilation time --> $DIR/trivial-unsized-projection.rs:20:12 | @@ -18,14 +24,13 @@ help: consider relaxing the implicit `Sized` restriction LL | type Assert: ?Sized | ++++++++ -error[E0277]: the size for values of type `[()]` cannot be known at compilation time +error[E0271]: type mismatch resolving `<[()] as Bad>::Assert == _` --> $DIR/trivial-unsized-projection.rs:20:36 | LL | const FOO: <[()] as Bad>::Assert = todo!(); - | ^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[()]` + | ^^^^^^^ types differ -error: aborting due to 2 previous errors +error: aborting due to 3 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..8b62356785a35 100644 --- a/tests/ui/traits/trivial-unsized-projection.rs +++ b/tests/ui/traits/trivial-unsized-projection.rs @@ -21,7 +21,8 @@ const FOO: <[()] as Bad>::Assert = todo!(); //[bad]~^ ERROR the size for values of type `[()]` cannot be known at compilation time //[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 == _` +//[bad_new]~| ERROR type mismatch resolving `<[()] as Bad>::Assert == _` #[cfg(any(good, good_new))] // Well-formed in trivially false param-env