Skip to content

Commit ab1fa19

Browse files
authored
Rollup merge of #121047 - compiler-errors:default-impls, r=lcnr
Do not assemble candidates for default impls There is no reason (as far as I can tell?) that we should assemble an impl candidate for a default impl. This candidate itself does not prove that the impl holds, and any time that it *does* hold, there will be a more specializing non-default impl that also is assembled. This is because `default impl<T> Foo for T {}` actually expands to `impl<T> Foo for T where T: Foo {}`. The only way to satisfy that where clause (without coinduction) is via *another* implementation that does hold -- precisely an impl that specializes it. This should fix the specialization related regressions for #116494. That should lead to one root crate regression that doesn't have to do with specialization, which I think we can regress. r? lcnr cc ``@rust-lang/types`` cc #31844
2 parents e499e99 + b4eee2e commit ab1fa19

File tree

9 files changed

+59
-40
lines changed

9 files changed

+59
-40
lines changed

compiler/rustc_trait_selection/src/solve/assembly/mod.rs

+14
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
337337
let mut consider_impls_for_simplified_type = |simp| {
338338
if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) {
339339
for &impl_def_id in impls_for_type {
340+
// For every `default impl`, there's always a non-default `impl`
341+
// that will *also* apply. There's no reason to register a candidate
342+
// for this impl, since it is *not* proof that the trait goal holds.
343+
if tcx.defaultness(impl_def_id).is_default() {
344+
return;
345+
}
346+
340347
match G::consider_impl_candidate(self, goal, impl_def_id) {
341348
Ok(candidate) => candidates.push(candidate),
342349
Err(NoSolution) => (),
@@ -440,6 +447,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
440447
let tcx = self.tcx();
441448
let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
442449
for &impl_def_id in trait_impls.blanket_impls() {
450+
// For every `default impl`, there's always a non-default `impl`
451+
// that will *also* apply. There's no reason to register a candidate
452+
// for this impl, since it is *not* proof that the trait goal holds.
453+
if tcx.defaultness(impl_def_id).is_default() {
454+
return;
455+
}
456+
443457
match G::consider_impl_candidate(self, goal, impl_def_id) {
444458
Ok(candidate) => candidates.push(candidate),
445459
Err(NoSolution) => (),

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

+8
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
566566
{
567567
return;
568568
}
569+
570+
// For every `default impl`, there's always a non-default `impl`
571+
// that will *also* apply. There's no reason to register a candidate
572+
// for this impl, since it is *not* proof that the trait goal holds.
573+
if self.tcx().defaultness(impl_def_id).is_default() {
574+
return;
575+
}
576+
569577
if self.reject_fn_ptr_impls(
570578
impl_def_id,
571579
obligation,

tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ default impl<T> Foo for T {
2020

2121
fn main() {
2222
println!("{}", MyStruct.foo_one());
23-
//~^ ERROR the method
23+
//~^ ERROR no method named `foo_one` found for struct `MyStruct` in the current scope
2424
}

tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr

+3-15
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,15 @@ LL | #![feature(specialization)]
88
= help: consider using `min_specialization` instead, which is more stable and complete
99
= note: `#[warn(incomplete_features)]` on by default
1010

11-
error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait bounds were not satisfied
11+
error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope
1212
--> $DIR/specialization-trait-not-implemented.rs:22:29
1313
|
1414
LL | struct MyStruct;
15-
| --------------- method `foo_one` not found for this struct because it doesn't satisfy `MyStruct: Foo`
15+
| --------------- method `foo_one` not found for this struct
1616
...
1717
LL | println!("{}", MyStruct.foo_one());
18-
| ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds
18+
| ^^^^^^^ method not found in `MyStruct`
1919
|
20-
note: trait bound `MyStruct: Foo` was not satisfied
21-
--> $DIR/specialization-trait-not-implemented.rs:14:1
22-
|
23-
LL | default impl<T> Foo for T {
24-
| ^^^^^^^^^^^^^^^^---^^^^^-
25-
| |
26-
| unsatisfied trait bound introduced here
27-
note: the trait `Foo` must be implemented
28-
--> $DIR/specialization-trait-not-implemented.rs:7:1
29-
|
30-
LL | trait Foo {
31-
| ^^^^^^^^^
3220
= help: items from traits can only be used if the trait is implemented and in scope
3321
note: `Foo` defines an item `foo_one`, perhaps you need to implement it
3422
--> $DIR/specialization-trait-not-implemented.rs:7:1

tests/ui/specialization/defaultimpl/validation.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ struct Z;
77
default impl S {} //~ ERROR inherent impls cannot be `default`
88

99
default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
10+
//~^ ERROR `S` cannot be sent between threads safely
1011
default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
1112
//~^ ERROR negative impls cannot be default impls
1213

tests/ui/specialization/defaultimpl/validation.stderr

+17-5
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,38 @@ LL | default unsafe impl Send for S {}
2626
| |
2727
| default because of this
2828

29+
error[E0277]: `S` cannot be sent between threads safely
30+
--> $DIR/validation.rs:9:1
31+
|
32+
LL | default unsafe impl Send for S {}
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `S` cannot be sent between threads safely
34+
|
35+
= help: the trait `Send` is not implemented for `S`
36+
= help: the trait `Send` is implemented for `S`
37+
= help: see issue #48214
38+
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
39+
2940
error: impls of auto traits cannot be default
30-
--> $DIR/validation.rs:10:15
41+
--> $DIR/validation.rs:11:15
3142
|
3243
LL | default impl !Send for Z {}
3344
| ------- ^^^^ auto trait
3445
| |
3546
| default because of this
3647

3748
error[E0750]: negative impls cannot be default impls
38-
--> $DIR/validation.rs:10:1
49+
--> $DIR/validation.rs:11:1
3950
|
4051
LL | default impl !Send for Z {}
4152
| ^^^^^^^ ^
4253

4354
error[E0750]: negative impls cannot be default impls
44-
--> $DIR/validation.rs:14:1
55+
--> $DIR/validation.rs:15:1
4556
|
4657
LL | default impl !Tr for S {}
4758
| ^^^^^^^ ^
4859

49-
error: aborting due to 5 previous errors; 1 warning emitted
60+
error: aborting due to 6 previous errors; 1 warning emitted
5061

51-
For more information about this error, try `rustc --explain E0750`.
62+
Some errors have detailed explanations: E0277, E0750.
63+
For more information about an error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
error[E0275]: overflow evaluating the requirement `T: Trait<_>`
2-
|
3-
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`)
4-
note: required for `T` to implement `Trait<_>`
5-
--> $DIR/issue-45814.rs:9:20
1+
error[E0119]: conflicting implementations of trait `Trait<_>`
2+
--> $DIR/issue-45814.rs:10:1
63
|
74
LL | default impl<T, U> Trait<T> for U {}
8-
| ^^^^^^^^ ^
9-
= note: 128 redundant requirements hidden
10-
= note: required for `T` to implement `Trait<_>`
5+
| --------------------------------- first implementation here
6+
LL |
7+
LL | impl<T> Trait<<T as Iterator>::Item> for T {}
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
119

1210
error: aborting due to 1 previous error
1311

14-
For more information about this error, try `rustc --explain E0275`.
12+
For more information about this error, try `rustc --explain E0119`.
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
error[E0275]: overflow evaluating the requirement `T: Trait<_>`
2-
|
3-
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`)
4-
note: required for `T` to implement `Trait<_>`
5-
--> $DIR/issue-45814.rs:9:20
1+
error[E0119]: conflicting implementations of trait `Trait<_>`
2+
--> $DIR/issue-45814.rs:10:1
63
|
74
LL | default impl<T, U> Trait<T> for U {}
8-
| ^^^^^^^^ ^
9-
= note: 128 redundant requirements hidden
10-
= note: required for `T` to implement `Trait<_>`
5+
| --------------------------------- first implementation here
6+
LL |
7+
LL | impl<T> Trait<<T as Iterator>::Item> for T {}
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
119

1210
error: aborting due to 1 previous error
1311

14-
For more information about this error, try `rustc --explain E0275`.
12+
For more information about this error, try `rustc --explain E0119`.

tests/ui/specialization/issue-45814.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//~ ERROR overflow evaluating the requirement `T: Trait<_>`
21
// revisions: current negative
32
#![feature(specialization)]
43
#![cfg_attr(negative, feature(with_negative_coherence))]
@@ -9,5 +8,6 @@ pub trait Trait<T> {}
98
default impl<T, U> Trait<T> for U {}
109

1110
impl<T> Trait<<T as Iterator>::Item> for T {}
11+
//~^ ERROR conflicting implementations of trait `Trait<_>`
1212

1313
fn main() {}

0 commit comments

Comments
 (0)