Skip to content

Commit e8c9dcc

Browse files
authored
Rollup merge of rust-lang#139791 - lcnr:ignore-global-where-bounds, r=compiler-errors
drop global where-bounds before merging candidates fixes rust-lang/trait-system-refactor-initiative#172 r? ```@compiler-errors```
2 parents 8118fca + 2c2c9df commit e8c9dcc

File tree

5 files changed

+93
-6
lines changed

5 files changed

+93
-6
lines changed

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -1256,10 +1256,11 @@ where
12561256
D: SolverDelegate<Interner = I>,
12571257
I: Interner,
12581258
{
1259+
#[instrument(level = "debug", skip(self, goal), ret)]
12591260
pub(super) fn merge_trait_candidates(
12601261
&mut self,
12611262
goal: Goal<I, TraitPredicate<I>>,
1262-
candidates: Vec<Candidate<I>>,
1263+
mut candidates: Vec<Candidate<I>>,
12631264
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
12641265
if let TypingMode::Coherence = self.typing_mode() {
12651266
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
@@ -1341,13 +1342,16 @@ where
13411342

13421343
// If there are *only* global where bounds, then make sure to return that this
13431344
// is still reported as being proven-via the param-env so that rigid projections
1344-
// operate correctly.
1345+
// operate correctly. Otherwise, drop all global where-bounds before merging the
1346+
// remaining candidates.
13451347
let proven_via =
13461348
if candidates.iter().all(|c| matches!(c.source, CandidateSource::ParamEnv(_))) {
13471349
TraitGoalProvenVia::ParamEnv
13481350
} else {
1351+
candidates.retain(|c| !matches!(c.source, CandidateSource::ParamEnv(_)));
13491352
TraitGoalProvenVia::Misc
13501353
};
1354+
13511355
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
13521356
if let Some(response) = self.try_merge_responses(&all_candidates) {
13531357
Ok((response, Some(proven_via)))

Diff for: tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs

+8
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,17 @@ where
3434
MultipleNested: Trait,
3535
{}
3636

37+
// We ignore the trivially true global where-bounds when checking that this
38+
// impl is well-formed, meaning that we depend on `MultipleNested: Trait` when
39+
// recursively proving `MultipleCandidates: Trait`.
40+
//
41+
// These overflow errors will disappear once we treat these cycles as either
42+
// productive or an error.
3743
impl Trait for MultipleNested
44+
//~^ ERROR overflow evaluating the requirement `MultipleNested: Trait`
3845
where
3946
MultipleCandidates: Trait,
47+
//~^ ERROR overflow evaluating the requirement `MultipleCandidates: Trait`
4048
DoesNotImpl: Trait,
4149
{}
4250

Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
1+
error[E0275]: overflow evaluating the requirement `MultipleNested: Trait`
2+
--> $DIR/inductive-cycle-but-err.rs:43:16
3+
|
4+
LL | impl Trait for MultipleNested
5+
| ^^^^^^^^^^^^^^
6+
7+
error[E0275]: overflow evaluating the requirement `MultipleCandidates: Trait`
8+
--> $DIR/inductive-cycle-but-err.rs:46:25
9+
|
10+
LL | MultipleCandidates: Trait,
11+
| ^^^^^
12+
113
error[E0277]: the trait bound `MultipleCandidates: Trait` is not satisfied
2-
--> $DIR/inductive-cycle-but-err.rs:46:19
14+
--> $DIR/inductive-cycle-but-err.rs:54:19
315
|
416
LL | impls_trait::<MultipleCandidates>();
517
| ^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `MultipleCandidates`
618
|
719
= help: the trait `Trait` is implemented for `MultipleCandidates`
820
note: required by a bound in `impls_trait`
9-
--> $DIR/inductive-cycle-but-err.rs:43:19
21+
--> $DIR/inductive-cycle-but-err.rs:51:19
1022
|
1123
LL | fn impls_trait<T: Trait>() {}
1224
| ^^^^^ required by this bound in `impls_trait`
1325

14-
error: aborting due to 1 previous error
26+
error: aborting due to 3 previous errors
1527

16-
For more information about this error, try `rustc --explain E0277`.
28+
Some errors have detailed explanations: E0275, E0277.
29+
For more information about an error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
//@ check-pass
5+
6+
// Regression test for trait-system-refactor-initiative#172.
7+
//
8+
// In this test the global where-bound simply constrains the
9+
// object lifetime bound to 'static while the builtin impl
10+
// ends up also emitting a `dyn Any: 'static` type outlives
11+
// constraint. This previously resulted in ambiguity. We now
12+
// always prefer the impl.
13+
14+
pub trait Any: 'static {}
15+
16+
pub trait Downcast<T>: Any
17+
where
18+
T: Any,
19+
{
20+
}
21+
22+
// elided object lifetime: `dyn Any + 'static`
23+
impl dyn Any {
24+
pub fn is<T>(&self)
25+
where
26+
T: Any,
27+
// elaboration adds global where-clause `dyn Any + 'static: Any`
28+
Self: Downcast<T>,
29+
{
30+
}
31+
}
32+
33+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
//@ check-pass
5+
6+
// Regression test for trait-system-refactor-initiative#172.
7+
//
8+
// The next-generation trait solver previously simply tried
9+
// to merge the global where-bounds with the impl candidates.
10+
// This caused ambiguity in case the where-bound had stricter
11+
// region requirements than the impl.
12+
13+
trait Trait {}
14+
struct Foo<'a, 'b>(&'a (), &'b ());
15+
impl<'a> Trait for Foo<'a, 'static> {}
16+
17+
fn impls_trait<T: Trait>() {}
18+
fn foo()
19+
where
20+
Foo<'static, 'static>: Trait,
21+
{
22+
// impl requires `'1 to be 'static
23+
// global where-bound requires both '0 and '1 to be 'static
24+
//
25+
// we always prefer the impl here.
26+
impls_trait::<Foo<'_, '_>>();
27+
}
28+
29+
fn main() {}

0 commit comments

Comments
 (0)