1
Fork 0

new solver: prefer trivial builtin impls over where-clauses

for now, only builtin `Sized` impls are tracked as being `Trivial`
This commit is contained in:
Rémy Rakic 2025-01-17 17:00:59 +00:00
parent 73c0ae6aec
commit 00844be421
8 changed files with 41 additions and 6 deletions

View file

@ -8,6 +8,7 @@ use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::CanonicalResponse;
use rustc_type_ir::visit::TypeVisitableExt as _;
use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate};
use smallvec::SmallVec;
use tracing::{instrument, trace};
use crate::delegate::SolverDelegate;
@ -225,7 +226,7 @@ where
}
ecx.probe_and_evaluate_goal_for_constituent_tys(
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
goal,
structural_traits::instantiate_constituent_tys_for_sized_trait,
)
@ -1194,7 +1195,30 @@ where
};
}
// FIXME: prefer trivial builtin impls
// We prefer trivial builtin candidates, i.e. builtin impls without any
// nested requirements, over all others. This is a fix for #53123 and
// prevents where-bounds from accidentally extending the lifetime of a
// variable.
if candidates
.iter()
.any(|c| matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial)))
{
let trivial_builtin_impls: SmallVec<[_; 1]> = candidates
.iter()
.filter(|c| {
matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
})
.map(|c| c.result)
.collect();
// There should only ever be a single trivial builtin candidate
// as they would otherwise overlap.
assert_eq!(trivial_builtin_impls.len(), 1);
return if let Some(response) = self.try_merge_responses(&trivial_builtin_impls) {
Ok((response, Some(TraitGoalProvenVia::Misc)))
} else {
Ok((self.bail_with_ambiguity(&trivial_builtin_impls), None))
};
}
// If there are non-global where-bounds, prefer where-bounds
// (including global ones) over everything else.