Skip to content

Commit a74b042

Browse files
Elaborate auto trait super traits in conv_object_poly_trait_ref
1 parent e927184 commit a74b042

8 files changed

+84
-61
lines changed

compiler/rustc_hir_analysis/src/astconv/object_safety.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds};
22
use crate::bounds::Bounds;
33
use crate::errors::TraitObjectDeclaredWithNoTraits;
4-
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
4+
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
55
use rustc_errors::struct_span_err;
66
use rustc_hir as hir;
77
use rustc_hir::def::{DefKind, Res};
@@ -83,7 +83,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
8383
let expanded_traits =
8484
traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b)));
8585

86-
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
86+
let (auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
8787
.filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
8888
.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
8989
if regular_traits.len() > 1 {
@@ -238,14 +238,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
238238
hir_trait_bounds,
239239
);
240240

241-
// De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
242-
// `dyn Trait + Send`.
243-
// We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
244-
// the bounds
245-
let mut duplicates = FxHashSet::default();
246-
auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id()));
247-
debug!("regular_traits: {:?}", regular_traits);
248-
debug!("auto_traits: {:?}", auto_traits);
241+
let auto_traits: FxIndexSet<DefId> = auto_traits
242+
.into_iter()
243+
.map(|info| info.trait_ref().def_id())
244+
.chain(regular_traits.iter().flat_map(|info| {
245+
traits::supertrait_def_ids(tcx, info.trait_ref().def_id())
246+
.filter(|def_id| tcx.trait_is_auto(*def_id))
247+
}))
248+
.collect();
249249

250250
// Erase the `dummy_self` (`trait_object_dummy_self`) used above.
251251
let existential_trait_refs = regular_traits.iter().map(|i| {
@@ -351,9 +351,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
351351

352352
let regular_trait_predicates = existential_trait_refs
353353
.map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
354-
let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| {
355-
ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()))
356-
});
354+
let auto_trait_predicates = auto_traits
355+
.into_iter()
356+
.map(|def_id| ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(def_id)));
357357
// N.b. principal, projections, auto traits
358358
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
359359
let mut v = regular_trait_predicates

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

+2
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
853853
let principal_trait_ref = principal.with_self_ty(tcx, self_ty);
854854
self.walk_vtable(principal_trait_ref, |ecx, assumption, vtable_base, _| {
855855
match G::consider_object_bound_candidate(ecx, goal, assumption.to_predicate(tcx)) {
856+
// FIXME: We could skip auto traits here, since they're eagerly elaborated in
857+
// <https://github.com/rust-lang/rust/pull/119825>.
856858
Ok(result) => candidates.push(Candidate {
857859
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Object {
858860
vtable_base,

tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ auto trait Marker2 {}
1212
trait Object: Marker1 {}
1313

1414
// A supertrait marker is illegal...
15-
impl !Marker1 for dyn Object + Marker2 {} //~ ERROR E0371
16-
//~^ ERROR 0321
15+
impl !Marker1 for dyn Object + Marker2 {}
16+
//~^ ERROR E0371
17+
//~| ERROR E0321
18+
//~| ERROR E0371
19+
1720
// ...and also a direct component.
1821
impl !Marker2 for dyn Object + Marker2 {} //~ ERROR E0371
1922
//~^ ERROR 0321
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,49 @@
1-
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
1+
error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1`
22
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
33
|
44
LL | impl !Marker1 for dyn Object + Marker2 {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1`
66

7-
error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
7+
error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1`
8+
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
9+
|
10+
LL | impl !Marker1 for dyn Object + Marker2 {}
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1`
12+
|
13+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
14+
15+
error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)`
816
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
917
|
1018
LL | impl !Marker1 for dyn Object + Marker2 {}
1119
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1220
|
1321
= note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
1422

15-
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
16-
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
23+
error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker2`
24+
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:21:1
1725
|
1826
LL | impl !Marker2 for dyn Object + Marker2 {}
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker2`
2028

21-
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
22-
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
29+
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)`
30+
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:21:1
2331
|
2432
LL | impl !Marker2 for dyn Object + Marker2 {}
2533
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2634
|
2735
= note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
2836

29-
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
30-
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1
37+
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + 'static)`
38+
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:29:1
3139
|
3240
LL | impl !Marker2 for dyn Object {}
3341
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3442
|
3543
= note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
3644

3745
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
38-
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:22:1
46+
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:25:1
3947
|
4048
LL | impl !Send for dyn Marker2 {}
4149
| ^^^^^^^^^^^^^^^-----------
@@ -45,27 +53,27 @@ LL | impl !Send for dyn Marker2 {}
4553
|
4654
= note: define and implement a trait or new type instead
4755

48-
error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)`
49-
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:27:1
56+
error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker1 + 'static)`
57+
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:30:1
5058
|
5159
LL | impl !Send for dyn Object {}
5260
| ^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
5361

54-
error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)`
55-
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:28:1
62+
error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker1 + Marker2 + 'static)`
63+
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:31:1
5664
|
5765
LL | impl !Send for dyn Object + Marker2 {}
5866
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
5967

6068
error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T`
61-
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:32:1
69+
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:35:1
6270
|
6371
LL | impl<T: ?Sized> !Marker3 for T {}
6472
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6573
|
6674
= note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds
6775

68-
error: aborting due to 9 previous errors
76+
error: aborting due to 10 previous errors
6977

7078
Some errors have detailed explanations: E0117, E0321, E0371.
7179
For more information about an error, try `rustc --explain E0117`.

tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ auto trait Marker2 {}
1212
trait Object: Marker1 {}
1313

1414
// A supertrait marker is illegal...
15-
impl Marker1 for dyn Object + Marker2 {} //~ ERROR E0371
16-
//~^ ERROR E0321
15+
impl Marker1 for dyn Object + Marker2 {}
16+
//~^ ERROR E0371
17+
//~| ERROR E0321
18+
//~| ERROR E0371
1719
// ...and also a direct component.
1820
impl Marker2 for dyn Object + Marker2 {} //~ ERROR E0371
1921
//~^ ERROR E0321
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,49 @@
1-
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
1+
error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1`
22
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
33
|
44
LL | impl Marker1 for dyn Object + Marker2 {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1`
66

7-
error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
7+
error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1`
8+
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
9+
|
10+
LL | impl Marker1 for dyn Object + Marker2 {}
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1`
12+
|
13+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
14+
15+
error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)`
816
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
917
|
1018
LL | impl Marker1 for dyn Object + Marker2 {}
1119
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1220
|
1321
= note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
1422

15-
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
16-
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1
23+
error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker2`
24+
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:20:1
1725
|
1826
LL | impl Marker2 for dyn Object + Marker2 {}
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker2`
2028

21-
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
22-
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1
29+
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)`
30+
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:20:1
2331
|
2432
LL | impl Marker2 for dyn Object + Marker2 {}
2533
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2634
|
2735
= note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
2836

29-
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
30-
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1
37+
error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + 'static)`
38+
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:28:1
3139
|
3240
LL | impl Marker2 for dyn Object {}
3341
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
3442
|
3543
= note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
3644

3745
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
38-
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:22:1
46+
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:24:1
3947
|
4048
LL | unsafe impl Send for dyn Marker2 {}
4149
| ^^^^^^^^^^^^^^^^^^^^^-----------
@@ -45,27 +53,27 @@ LL | unsafe impl Send for dyn Marker2 {}
4553
|
4654
= note: define and implement a trait or new type instead
4755

48-
error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)`
49-
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:27:1
56+
error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker1 + 'static)`
57+
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:29:1
5058
|
5159
LL | unsafe impl Send for dyn Object {}
5260
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
5361

54-
error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)`
55-
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:28:1
62+
error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker1 + Marker2 + 'static)`
63+
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:30:1
5664
|
5765
LL | unsafe impl Send for dyn Object + Marker2 {}
5866
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
5967

6068
error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T`
61-
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:32:1
69+
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:34:1
6270
|
6371
LL | impl<T: ?Sized> Marker3 for T {}
6472
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6573
|
6674
= note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds
6775

68-
error: aborting due to 9 previous errors
76+
error: aborting due to 10 previous errors
6977

7078
Some errors have detailed explanations: E0117, E0321, E0371.
7179
For more information about an error, try `rustc --explain E0117`.

tests/ui/traits/trait-upcasting/subtrait-method.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,17 @@ fn main() {
5151

5252
let bar: &dyn Bar = baz;
5353
bar.c();
54-
//~^ ERROR no method named `c` found for reference `&dyn Bar` in the current scope [E0599]
54+
//~^ ERROR no method named `c` found for reference `&dyn Bar + Send + Sync` in the current scope [E0599]
5555

5656
let foo: &dyn Foo = baz;
5757
foo.b();
58-
//~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599]
58+
//~^ ERROR no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599]
5959
foo.c();
60-
//~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599]
60+
//~^ ERROR no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599]
6161

6262
let foo: &dyn Foo = bar;
6363
foo.b();
64-
//~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599]
64+
//~^ ERROR no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599]
6565
foo.c();
66-
//~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599]
66+
//~^ ERROR no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599]
6767
}

tests/ui/traits/trait-upcasting/subtrait-method.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope
1+
error[E0599]: no method named `c` found for reference `&dyn Bar + Send + Sync` in the current scope
22
--> $DIR/subtrait-method.rs:53:9
33
|
44
LL | bar.c();
@@ -11,7 +11,7 @@ note: `Baz` defines an item `c`, perhaps you need to implement it
1111
LL | trait Baz: Bar {
1212
| ^^^^^^^^^^^^^^
1313

14-
error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
14+
error[E0599]: no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope
1515
--> $DIR/subtrait-method.rs:57:9
1616
|
1717
LL | foo.b();
@@ -24,7 +24,7 @@ note: `Bar` defines an item `b`, perhaps you need to implement it
2424
LL | trait Bar: Foo {
2525
| ^^^^^^^^^^^^^^
2626

27-
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
27+
error[E0599]: no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope
2828
--> $DIR/subtrait-method.rs:59:9
2929
|
3030
LL | foo.c();
@@ -37,7 +37,7 @@ note: `Baz` defines an item `c`, perhaps you need to implement it
3737
LL | trait Baz: Bar {
3838
| ^^^^^^^^^^^^^^
3939

40-
error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
40+
error[E0599]: no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope
4141
--> $DIR/subtrait-method.rs:63:9
4242
|
4343
LL | foo.b();
@@ -50,7 +50,7 @@ note: `Bar` defines an item `b`, perhaps you need to implement it
5050
LL | trait Bar: Foo {
5151
| ^^^^^^^^^^^^^^
5252

53-
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
53+
error[E0599]: no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope
5454
--> $DIR/subtrait-method.rs:65:9
5555
|
5656
LL | foo.c();

0 commit comments

Comments
 (0)