Skip to content

Commit 00844be

Browse files
committed
new solver: prefer trivial builtin impls over where-clauses
for now, only builtin `Sized` impls are tracked as being `Trivial`
1 parent 73c0ae6 commit 00844be

File tree

8 files changed

+41
-6
lines changed

8 files changed

+41
-6
lines changed

Diff for: Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4259,6 +4259,7 @@ dependencies = [
42594259
"rustc_serialize",
42604260
"rustc_type_ir",
42614261
"rustc_type_ir_macros",
4262+
"smallvec",
42624263
"tracing",
42634264
]
42644265

Diff for: compiler/rustc_next_trait_solver/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ rustc_macros = { path = "../rustc_macros", optional = true }
1313
rustc_serialize = { path = "../rustc_serialize", optional = true }
1414
rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
1515
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
16+
smallvec = "1.8.1"
1617
tracing = "0.1"
1718
# tidy-alphabetical-end
1819

Diff for: compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_type_ir::lang_items::TraitSolverLangItem;
88
use rustc_type_ir::solve::CanonicalResponse;
99
use rustc_type_ir::visit::TypeVisitableExt as _;
1010
use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate};
11+
use smallvec::SmallVec;
1112
use tracing::{instrument, trace};
1213

1314
use crate::delegate::SolverDelegate;
@@ -225,7 +226,7 @@ where
225226
}
226227

227228
ecx.probe_and_evaluate_goal_for_constituent_tys(
228-
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
229+
CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
229230
goal,
230231
structural_traits::instantiate_constituent_tys_for_sized_trait,
231232
)
@@ -1194,7 +1195,30 @@ where
11941195
};
11951196
}
11961197

1197-
// FIXME: prefer trivial builtin impls
1198+
// We prefer trivial builtin candidates, i.e. builtin impls without any
1199+
// nested requirements, over all others. This is a fix for #53123 and
1200+
// prevents where-bounds from accidentally extending the lifetime of a
1201+
// variable.
1202+
if candidates
1203+
.iter()
1204+
.any(|c| matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial)))
1205+
{
1206+
let trivial_builtin_impls: SmallVec<[_; 1]> = candidates
1207+
.iter()
1208+
.filter(|c| {
1209+
matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
1210+
})
1211+
.map(|c| c.result)
1212+
.collect();
1213+
// There should only ever be a single trivial builtin candidate
1214+
// as they would otherwise overlap.
1215+
assert_eq!(trivial_builtin_impls.len(), 1);
1216+
return if let Some(response) = self.try_merge_responses(&trivial_builtin_impls) {
1217+
Ok((response, Some(TraitGoalProvenVia::Misc)))
1218+
} else {
1219+
Ok((self.bail_with_ambiguity(&trivial_builtin_impls), None))
1220+
};
1221+
}
11981222

11991223
// If there are non-global where-bounds, prefer where-bounds
12001224
// (including global ones) over everything else.

Diff for: compiler/rustc_trait_selection/src/traits/project.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
991991
Err(ErrorGuaranteed { .. }) => true,
992992
}
993993
}
994-
ImplSource::Builtin(BuiltinImplSource::Misc, _) => {
994+
ImplSource::Builtin(BuiltinImplSource::Misc | BuiltinImplSource::Trivial, _) => {
995995
// While a builtin impl may be known to exist, the associated type may not yet
996996
// be known. Any type with multiple potential associated types is therefore
997997
// not eligible.
@@ -1296,7 +1296,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
12961296
) -> Progress<'tcx> {
12971297
match impl_source {
12981298
ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
1299-
ImplSource::Builtin(BuiltinImplSource::Misc, data) => {
1299+
ImplSource::Builtin(BuiltinImplSource::Misc | BuiltinImplSource::Trivial, data) => {
13001300
let tcx = selcx.tcx();
13011301
let trait_def_id = obligation.predicate.trait_def_id(tcx);
13021302
if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) {

Diff for: compiler/rustc_ty_utils/src/instance.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ fn resolve_associated_item<'tcx>(
248248
})
249249
}
250250
}
251-
traits::ImplSource::Builtin(BuiltinImplSource::Misc, _) => {
251+
traits::ImplSource::Builtin(BuiltinImplSource::Misc | BuiltinImplSource::Trivial, _) => {
252252
if tcx.is_lang_item(trait_ref.def_id, LangItem::Clone) {
253253
// FIXME(eddyb) use lang items for methods instead of names.
254254
let name = tcx.item_name(trait_item_id);

Diff for: compiler/rustc_type_ir/src/solve/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ pub enum CandidateSource<I: Interner> {
169169
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
170170
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))]
171171
pub enum BuiltinImplSource {
172+
/// A built-in impl that is considered trivial, without any nested requirements. They
173+
/// are preferred over where-clauses, and we want to track them explicitly.
174+
Trivial,
172175
/// Some built-in impl we don't need to differentiate. This should be used
173176
/// unless more specific information is necessary.
174177
Misc,

Diff for: tests/ui/regions/issue-26448-1.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
//@ run-pass
1+
//@ revisions: current next
2+
//@ [next] compile-flags: -Znext-solver
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@ check-pass
25

36
pub trait Foo<T> {
47
fn foo(self) -> T;

Diff for: tests/ui/regions/issue-26448-2.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//@ revisions: current next
2+
//@ [next] compile-flags: -Znext-solver
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
14
//@ check-pass
25

36
pub struct Bar<T> {

0 commit comments

Comments
 (0)