diff options
Diffstat (limited to 'compiler/rustc_next_trait_solver')
5 files changed, 57 insertions, 23 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 b2d40146348..231fb3e2964 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -21,7 +21,7 @@ use crate::delegate::SolverDelegate; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource, - MaybeCause, NoSolution, ParamEnvSource, QueryResult, + MaybeCause, NoSolution, ParamEnvSource, QueryResult, has_no_inference_or_external_constraints, }; enum AliasBoundKind { @@ -50,7 +50,7 @@ where fn trait_ref(self, cx: I) -> ty::TraitRef<I>; - fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self; + fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self; fn trait_def_id(self, cx: I) -> I::DefId; @@ -376,8 +376,8 @@ where return self.forced_ambiguity(MaybeCause::Ambiguity).into_iter().collect(); } - let goal: Goal<I, G> = - goal.with(self.cx(), goal.predicate.with_self_ty(self.cx(), normalized_self_ty)); + let goal: Goal<I, G> = goal + .with(self.cx(), goal.predicate.with_replaced_self_ty(self.cx(), normalized_self_ty)); // Vars that show up in the rest of the goal substs may have been constrained by // normalizing the self type as well, since type variables are not uniquified. let goal = self.resolve_vars_if_possible(goal); @@ -395,9 +395,30 @@ where match assemble_from { AssembleCandidatesFrom::All => { - self.assemble_impl_candidates(goal, &mut candidates); self.assemble_builtin_impl_candidates(goal, &mut candidates); - self.assemble_object_bound_candidates(goal, &mut candidates); + // For performance we only assemble impls if there are no candidates + // which would shadow them. This is necessary to avoid hangs in rayon, + // see trait-system-refactor-initiative#109 for more details. + // + // We always assemble builtin impls as trivial builtin impls have a higher + // priority than where-clauses. + // + // We only do this if any such candidate applies without any constraints + // as we may want to weaken inference guidance in the future and don't want + // to worry about causing major performance regressions when doing so. + // See trait-system-refactor-initiative#226 for some ideas here. + if TypingMode::Coherence == self.typing_mode() + || !candidates.iter().any(|c| { + matches!( + c.source, + CandidateSource::ParamEnv(ParamEnvSource::NonGlobal) + | CandidateSource::AliasBound + ) && has_no_inference_or_external_constraints(c.result) + }) + { + self.assemble_impl_candidates(goal, &mut candidates); + self.assemble_object_bound_candidates(goal, &mut candidates); + } } AssembleCandidatesFrom::EnvAndBounds => {} } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index c0bebdf6fb6..faa86734d08 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -75,9 +75,16 @@ where Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()])) } - ty::Coroutine(_, args) => { + ty::Coroutine(def_id, args) => { let coroutine_args = args.as_coroutine(); - Ok(ty::Binder::dummy(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()])) + Ok(ty::Binder::dummy(vec![ + coroutine_args.tupled_upvars_ty(), + Ty::new_coroutine_witness( + ecx.cx(), + def_id, + ecx.cx().mk_args(coroutine_args.parent_args().as_slice()), + ), + ])) } ty::CoroutineWitness(def_id, args) => Ok(ecx @@ -245,7 +252,14 @@ where Movability::Movable => { if ecx.cx().features().coroutine_clone() { let coroutine = args.as_coroutine(); - Ok(ty::Binder::dummy(vec![coroutine.tupled_upvars_ty(), coroutine.witness()])) + Ok(ty::Binder::dummy(vec![ + coroutine.tupled_upvars_ty(), + Ty::new_coroutine_witness( + ecx.cx(), + def_id, + ecx.cx().mk_args(coroutine.parent_args().as_slice()), + ), + ])) } else { Err(NoSolution) } 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 61f3f9367f0..9a22bf58c03 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -29,8 +29,8 @@ where self.trait_ref } - fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self { - self.with_self_ty(cx, self_ty) + fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + self.with_replaced_self_ty(cx, self_ty) } fn trait_def_id(self, _: I) -> I::DefId { 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 1e0a90eb2ee..93434dce79f 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 @@ -99,8 +99,8 @@ where self.alias.trait_ref(cx) } - fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self { - self.with_self_ty(cx, self_ty) + fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + self.with_replaced_self_ty(cx, self_ty) } fn trait_def_id(self, cx: I) -> I::DefId { 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 650b85d99d2..f760c2c07ff 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -33,8 +33,8 @@ where self.trait_ref } - fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self { - self.with_self_ty(cx, self_ty) + fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + self.with_replaced_self_ty(cx, self_ty) } fn trait_def_id(self, _: I) -> I::DefId { @@ -229,7 +229,7 @@ where } // We need to make sure to stall any coroutines we are inferring to avoid query cycles. - if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) { + if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) { return cand; } @@ -294,7 +294,7 @@ where } // We need to make sure to stall any coroutines we are inferring to avoid query cycles. - if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) { + if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) { return cand; } @@ -1263,7 +1263,9 @@ where let goals = ecx.enter_forall(constituent_tys(ecx, goal.predicate.self_ty())?, |ecx, tys| { tys.into_iter() - .map(|ty| goal.with(ecx.cx(), goal.predicate.with_self_ty(ecx.cx(), ty))) + .map(|ty| { + goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty)) + }) .collect::<Vec<_>>() }); ecx.add_goals(GoalSource::ImplWhereBound, goals); @@ -1432,11 +1434,8 @@ where self.merge_trait_candidates(candidates) } - fn try_stall_coroutine_witness( - &mut self, - self_ty: I::Ty, - ) -> Option<Result<Candidate<I>, NoSolution>> { - if let ty::CoroutineWitness(def_id, _) = self_ty.kind() { + fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> { + if let ty::Coroutine(def_id, _) = self_ty.kind() { match self.typing_mode() { TypingMode::Analysis { defining_opaque_types_and_generators: stalled_generators, |
