Skip to content

Commit eb49408

Browse files
committed
drop some impl candidates before evaluating candidates
1 parent f80e454 commit eb49408

File tree

8 files changed

+50
-168
lines changed

8 files changed

+50
-168
lines changed

compiler/rustc_error_codes/src/error_codes/E0275.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ trait Foo {}
88
struct Bar<T>(T);
99
1010
impl<T> Foo for T where Bar<T>: Foo {}
11+
12+
fn takes_foo<T: Foo>() {}
13+
14+
fn calls_takes_foo() {
15+
takes_foo::<()>();
16+
}
1117
```
1218

1319
This error occurs when there was a recursive trait requirement that overflowed

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,33 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
157157

158158
// Winnow, but record the exact outcome of evaluation, which
159159
// is needed for specialization. Propagate overflow if it occurs.
160+
let mut eval_cand = |c| match self.evaluate_candidate(stack, &c) {
161+
Ok(eval) if eval.may_apply() => {
162+
Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
163+
}
164+
Ok(_) => Ok(None),
165+
Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)),
166+
Err(OverflowError::ErrorReporting) => Err(ErrorReporting),
167+
Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))),
168+
};
169+
170+
// this is very not perf and should be fixed xd
171+
let drop_impl_candidates = candidates
172+
.iter()
173+
.filter(|c| matches!(c, SelectionCandidate::ParamCandidate(_)))
174+
.cloned()
175+
.map(&mut eval_cand)
176+
.flat_map(Result::transpose)
177+
.try_fold(false, |should_drop, param_candidate| {
178+
let cand = &param_candidate?.candidate;
179+
Ok::<_, SelectionError<'_>>(
180+
should_drop || !(cand.is_global() && !cand.has_late_bound_regions()),
181+
)
182+
})?;
160183
let mut candidates = candidates
161184
.into_iter()
162-
.map(|c| match self.evaluate_candidate(stack, &c) {
163-
Ok(eval) if eval.may_apply() => {
164-
Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
165-
}
166-
Ok(_) => Ok(None),
167-
Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)),
168-
Err(OverflowError::ErrorReporting) => Err(ErrorReporting),
169-
Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))),
170-
})
185+
.filter(|c| !matches!(c, SelectionCandidate::ImplCandidate(_) if drop_impl_candidates))
186+
.map(&mut eval_cand)
171187
.flat_map(Result::transpose)
172188
.collect::<Result<Vec<_>, _>>()?;
173189

src/test/ui/const-generics/issues/issue-90318.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@ fn consume<T: 'static>(_val: T)
1313
where
1414
If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
1515
//~^ ERROR: overly complex generic constant
16-
//~| ERROR: cannot call non-const operator in constants
1716
{
1817
}
1918

2019
fn test<T: 'static>()
2120
where
2221
If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
2322
//~^ ERROR: overly complex generic constant
24-
//~| ERROR: cannot call non-const operator in constants
2523
{
2624
}
2725

src/test/ui/const-generics/issues/issue-90318.stderr

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,8 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
99
= help: consider moving this anonymous constant into a `const` function
1010
= note: this operation may be supported in the future
1111

12-
error[E0015]: cannot call non-const operator in constants
13-
--> $DIR/issue-90318.rs:14:10
14-
|
15-
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17-
|
18-
note: impl defined here, but it is not `const`
19-
--> $SRC_DIR/core/src/any.rs:LL:COL
20-
|
21-
LL | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
22-
| ^^^^^^^^^
23-
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
24-
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
25-
2612
error: overly complex generic constant
27-
--> $DIR/issue-90318.rs:22:8
13+
--> $DIR/issue-90318.rs:21:8
2814
|
2915
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
3016
| ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,20 +20,5 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
3420
= help: consider moving this anonymous constant into a `const` function
3521
= note: this operation may be supported in the future
3622

37-
error[E0015]: cannot call non-const operator in constants
38-
--> $DIR/issue-90318.rs:22:10
39-
|
40-
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42-
|
43-
note: impl defined here, but it is not `const`
44-
--> $SRC_DIR/core/src/any.rs:LL:COL
45-
|
46-
LL | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
47-
| ^^^^^^^^^
48-
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
49-
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
50-
51-
error: aborting due to 4 previous errors
23+
error: aborting due to 2 previous errors
5224

53-
For more information about this error, try `rustc --explain E0015`.

src/test/ui/error-codes/E0275.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ trait Foo {}
22

33
struct Bar<T>(T);
44

5-
impl<T> Foo for T where Bar<T>: Foo {} //~ ERROR E0275
5+
impl<T> Foo for T where Bar<T>: Foo {}
6+
7+
fn takes_foo<T: Foo>() {}
68

79
fn main() {
10+
takes_foo::<()>(); //~ ERROR E0275
811
}

src/test/ui/error-codes/E0275.stderr

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1-
error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
2-
--> $DIR/E0275.rs:5:33
1+
error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<()>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
2+
--> $DIR/E0275.rs:10:5
33
|
4-
LL | impl<T> Foo for T where Bar<T>: Foo {}
5-
| ^^^
4+
LL | takes_foo::<()>();
5+
| ^^^^^^^^^^^^^^^
66
|
77
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
8-
note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
8+
note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<()>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
99
--> $DIR/E0275.rs:5:9
1010
|
1111
LL | impl<T> Foo for T where Bar<T>: Foo {}
1212
| ^^^ ^
1313
= note: 127 redundant requirements hidden
14-
= note: required because of the requirements on the impl of `Foo` for `Bar<T>`
14+
= note: required because of the requirements on the impl of `Foo` for `()`
15+
note: required by a bound in `takes_foo`
16+
--> $DIR/E0275.rs:7:17
17+
|
18+
LL | fn takes_foo<T: Foo>() {}
19+
| ^^^ required by this bound in `takes_foo`
1520

1621
error: aborting due to previous error
1722

src/test/ui/issues/issue-20413.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ struct NoData<T>;
66
//~^ ERROR: parameter `T` is never used
77

88
impl<T> Foo for T where NoData<T>: Foo {
9-
//~^ ERROR: overflow evaluating the requirement
10-
//~| ERROR: overflow evaluating the requirement
119
fn answer(self) {
1210
let val: NoData<T> = NoData;
1311
}
@@ -26,16 +24,12 @@ struct AlmostNoData<T>(Option<T>);
2624
struct EvenLessData<T>(Option<T>);
2725

2826
impl<T> Bar for T where EvenLessData<T>: Baz {
29-
//~^ ERROR: overflow evaluating the requirement
30-
//~| ERROR: overflow evaluating the requirement
3127
fn answer(self) {
3228
let val: EvenLessData<T> = EvenLessData(None);
3329
}
3430
}
3531

3632
impl<T> Baz for T where AlmostNoData<T>: Bar {
37-
//~^ ERROR: overflow evaluating the requirement
38-
//~| ERROR: overflow evaluating the requirement
3933
fn answer(self) {
4034
let val: NoData<T> = AlmostNoData(None);
4135
}

0 commit comments

Comments
 (0)