refactor compute_goal_fast_path: turn into a single match

This commit is contained in:
Jana Dönszelmann
2026-05-01 11:23:57 +02:00
parent 4ddd4538a8
commit 644250d8b6
@@ -13,7 +13,7 @@
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::Certainty;
use rustc_middle::ty::{
self, MayBeErased, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
self, MayBeErased, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt, TypingMode,
};
use rustc_span::{DUMMY_SP, Span};
@@ -73,51 +73,60 @@ fn compute_goal_fast_path(
goal: Goal<'tcx, ty::Predicate<'tcx>>,
span: Span,
) -> Option<Certainty> {
if let Some(trait_pred) = goal.predicate.as_trait_clause() {
if self.shallow_resolve(trait_pred.self_ty().skip_binder()).is_ty_var()
let pred = goal.predicate.kind();
match pred.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
let trait_pred = pred.rebind(trait_pred);
if self.shallow_resolve(trait_pred.self_ty().skip_binder()).is_ty_var()
// We don't do this fast path when opaques are defined since we may
// eventually use opaques to incompletely guide inference via ty var
// self types.
// FIXME: Properly consider opaques here.
&& self.known_no_opaque_types_in_storage()
{
return Some(Certainty::AMBIGUOUS);
}
if trait_pred.polarity() == ty::PredicatePolarity::Positive {
match self.0.tcx.as_lang_item(trait_pred.def_id()) {
Some(LangItem::Sized) | Some(LangItem::MetaSized) => {
let predicate = self.resolve_vars_if_possible(goal.predicate);
if sizedness_fast_path(self.tcx, predicate, goal.param_env) {
return Some(Certainty::Yes);
{
Some(Certainty::AMBIGUOUS)
} else if trait_pred.polarity() == ty::PredicatePolarity::Positive {
match self.0.tcx.as_lang_item(trait_pred.def_id()) {
Some(LangItem::Sized) | Some(LangItem::MetaSized) => {
let predicate = self.resolve_vars_if_possible(goal.predicate);
if sizedness_fast_path(self.tcx, predicate, goal.param_env) {
return Some(Certainty::Yes);
} else {
None
}
}
}
Some(LangItem::Copy | LangItem::Clone) => {
let self_ty =
self.resolve_vars_if_possible(trait_pred.self_ty().skip_binder());
// Unlike `Sized` traits, which always prefer the built-in impl,
// `Copy`/`Clone` may be shadowed by a param-env candidate which
// could force a lifetime error or guide inference. While that's
// not generally desirable, it is observable, so for now let's
// ignore this fast path for types that have regions or infer.
if !self_ty
.has_type_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_INFER)
&& self_ty.is_trivially_pure_clone_copy()
{
return Some(Certainty::Yes);
Some(LangItem::Copy | LangItem::Clone) => {
let self_ty =
self.resolve_vars_if_possible(trait_pred.self_ty().skip_binder());
// Unlike `Sized` traits, which always prefer the built-in impl,
// `Copy`/`Clone` may be shadowed by a param-env candidate which
// could force a lifetime error or guide inference. While that's
// not generally desirable, it is observable, so for now let's
// ignore this fast path for types that have regions or infer.
if !self_ty
.has_type_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_INFER)
&& self_ty.is_trivially_pure_clone_copy()
{
return Some(Certainty::Yes);
} else {
None
}
}
_ => None,
}
_ => {}
} else {
None
}
}
}
let pred = goal.predicate.kind();
match pred.no_bound_vars()? {
ty::PredicateKind::DynCompatible(def_id) if self.0.tcx.is_dyn_compatible(def_id) => {
Some(Certainty::Yes)
}
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(outlives)) => {
if outlives.has_escaping_bound_vars() {
return None;
}
self.0.sub_regions(
SubregionOrigin::RelateRegionParamBound(span, None),
outlives.1,
@@ -127,6 +136,10 @@ fn compute_goal_fast_path(
Some(Certainty::Yes)
}
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
if outlives.has_escaping_bound_vars() {
return None;
}
self.0.register_type_outlives_constraint(
outlives.0,
outlives.1,
@@ -137,6 +150,10 @@ fn compute_goal_fast_path(
}
ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, .. })
| ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
if a.has_escaping_bound_vars() || b.has_escaping_bound_vars() {
return None;
}
match (self.shallow_resolve(a).kind(), self.shallow_resolve(b).kind()) {
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
self.sub_unify_ty_vids_raw(a_vid, b_vid);
@@ -146,6 +163,10 @@ fn compute_goal_fast_path(
}
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) => {
if ct.has_escaping_bound_vars() {
return None;
}
if self.shallow_resolve_const(ct).is_ct_infer() {
Some(Certainty::AMBIGUOUS)
} else {
@@ -153,6 +174,10 @@ fn compute_goal_fast_path(
}
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
if arg.has_escaping_bound_vars() {
return None;
}
let arg = self.shallow_resolve_term(arg);
if arg.is_trivially_wf(self.tcx) {
Some(Certainty::Yes)