From 8a21d1b495556554dc4ee55338423870b4f7dd53 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 May 2025 16:27:48 +0000 Subject: [PATCH] Review --- .../src/solve/assembly/mod.rs | 24 ++++++++++++++----- .../src/solve/effect_goals.rs | 4 +--- .../src/solve/eval_ctxt/mod.rs | 12 +++++----- .../src/solve/normalizes_to/mod.rs | 4 +--- .../src/solve/trait_goals.rs | 4 +--- compiler/rustc_type_ir/src/solve/mod.rs | 5 ++-- 6 files changed, 29 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 0cc46a0670e4..345a272895d3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -123,7 +123,7 @@ where result: Ok(candidate.result), }, Err(NoSolution) => inspect::ProbeKind::TraitCandidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), + source: CandidateSource::ParamEnv(ParamEnvSource::Global), result: Err(NoSolution), }, }) @@ -157,7 +157,7 @@ where } /// Try to reject the assumption based off of simple heuristics, such as [`ty::ClauseKind`] - /// and [`I::DefId`]. + /// and `DefId`. fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, goal: Goal, @@ -990,12 +990,26 @@ where } } + /// Compute whether a param-env assumption is global or non-global after normalizing it. + /// + /// This is necessary because, for example, given: + /// + /// ```ignore,rust + /// where + /// T: Trait, + /// i32: From, + /// ``` + /// + /// The `i32: From` bound is non-global before normalization, but is global after. + /// Since the old trait solver normalized param-envs eagerly, we want to emulate this + /// behavior lazily. fn characterize_param_env_assumption( &mut self, param_env: I::ParamEnv, assumption: I::Clause, ) -> Result, NoSolution> { - // FIXME: + // FIXME: This should be fixed, but it also requires changing the behavior + // in the old solver which is currently relied on. if assumption.has_bound_vars() { return Ok(CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)); } @@ -1030,7 +1044,6 @@ where let Ok(ty) = self.ecx.structurally_normalize_ty(self.param_env, ty) else { return ControlFlow::Break(Err(NoSolution)); }; - let ty = self.ecx.eager_resolve(ty); if let ty::Placeholder(_) = ty.kind() { ControlFlow::Break(Ok(())) @@ -1043,7 +1056,6 @@ where let Ok(ct) = self.ecx.structurally_normalize_const(self.param_env, ct) else { return ControlFlow::Break(Err(NoSolution)); }; - let ct = self.ecx.eager_resolve(ct); if let ty::ConstKind::Placeholder(_) = ct.kind() { ControlFlow::Break(Ok(())) @@ -1053,7 +1065,7 @@ where } fn visit_region(&mut self, r: I::Region) -> Self::Result { - match r.kind() { + match self.ecx.eager_resolve_region(r).kind() { ty::ReStatic | ty::ReError(_) => ControlFlow::Continue(()), ty::ReVar(_) | ty::RePlaceholder(_) => ControlFlow::Break(Ok(())), ty::ReErased | ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReBound(..) => { diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index ab0ba1005530..84a83d79cf04 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -62,9 +62,7 @@ where goal: Goal, assumption: I::Clause, ) -> Result<(), NoSolution> { - let Some(host_clause) = assumption.as_host_effect_clause() else { - panic!("fast_reject_assumption should have avoided this"); - }; + let host_clause = assumption.as_host_effect_clause().unwrap(); let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; 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 4a9daad1746f..bf9f21d05f6c 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 @@ -19,7 +19,6 @@ use tracing::{debug, instrument, trace}; use super::has_only_region_constraints; use crate::coherence; use crate::delegate::SolverDelegate; -use crate::resolve::EagerResolver; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ @@ -1001,11 +1000,12 @@ where self.delegate.resolve_vars_if_possible(value) } - pub(super) fn eager_resolve(&self, value: T) -> T - where - T: TypeFoldable, - { - value.fold_with(&mut EagerResolver::new(self.delegate)) + pub(super) fn eager_resolve_region(&self, r: I::Region) -> I::Region { + if let ty::ReVar(vid) = r.kind() { + self.delegate.opportunistic_resolve_lt_var(vid) + } else { + r + } } pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs { diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 9c17a15bb0e1..b90e34e78101 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -130,9 +130,7 @@ where goal: Goal, assumption: I::Clause, ) -> Result<(), NoSolution> { - let Some(projection_pred) = assumption.as_projection_clause() else { - panic!("fast_reject_assumption should have avoided this"); - }; + let projection_pred = assumption.as_projection_clause().unwrap(); let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?; diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 4d42bb137f0b..e3addf8bf93f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -151,9 +151,7 @@ where goal: Goal, assumption: I::Clause, ) -> Result<(), NoSolution> { - let Some(trait_clause) = assumption.as_trait_clause() else { - panic!("fast_reject_assumption should have avoided this"); - }; + let trait_clause = assumption.as_trait_clause().unwrap(); let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 994ec2b341dc..e45a7b7fbc16 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -147,9 +147,8 @@ pub enum CandidateSource { /// For a list of all traits with builtin impls, check out the /// `EvalCtxt::assemble_builtin_impl_candidates` method. BuiltinImpl(BuiltinImplSource), - /// An assumption from the environment. - /// - /// More precisely we've used the `n-th` assumption in the `param_env`. + /// An assumption from the environment. Stores a [`ParamEnvSource`], since we + /// prefer non-global param-env candidates in candidate assembly. /// /// ## Examples ///