From a74b042e70b9952b9364ff4327f3f873c97e1255 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 10 Jan 2024 17:51:07 +0000 Subject: [PATCH 1/3] Elaborate auto trait super traits in conv_object_poly_trait_ref --- .../src/astconv/object_safety.rs | 26 ++++++------ .../src/solve/assembly/mod.rs | 2 + ...ce-impl-trait-for-marker-trait-negative.rs | 7 +++- ...mpl-trait-for-marker-trait-negative.stderr | 42 +++++++++++-------- ...ce-impl-trait-for-marker-trait-positive.rs | 6 ++- ...mpl-trait-for-marker-trait-positive.stderr | 42 +++++++++++-------- .../traits/trait-upcasting/subtrait-method.rs | 10 ++--- .../trait-upcasting/subtrait-method.stderr | 10 ++--- 8 files changed, 84 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 703e0bdc40edb..9ccb462e6729a 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -1,7 +1,7 @@ use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds}; use crate::bounds::Bounds; use crate::errors::TraitObjectDeclaredWithNoTraits; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -83,7 +83,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let expanded_traits = traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b))); - let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits + let (auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { @@ -238,14 +238,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir_trait_bounds, ); - // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as - // `dyn Trait + Send`. - // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering - // the bounds - let mut duplicates = FxHashSet::default(); - auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id())); - debug!("regular_traits: {:?}", regular_traits); - debug!("auto_traits: {:?}", auto_traits); + let auto_traits: FxIndexSet = auto_traits + .into_iter() + .map(|info| info.trait_ref().def_id()) + .chain(regular_traits.iter().flat_map(|info| { + traits::supertrait_def_ids(tcx, info.trait_ref().def_id()) + .filter(|def_id| tcx.trait_is_auto(*def_id)) + })) + .collect(); // Erase the `dummy_self` (`trait_object_dummy_self`) used above. let existential_trait_refs = regular_traits.iter().map(|i| { @@ -351,9 +351,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let regular_trait_predicates = existential_trait_refs .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); - let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| { - ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())) - }); + let auto_trait_predicates = auto_traits + .into_iter() + .map(|def_id| ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(def_id))); // N.b. principal, projections, auto traits // FIXME: This is actually wrong with multiple principals in regards to symbol mangling let mut v = regular_trait_predicates diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index caf9470b4c646..7a827fd263343 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -853,6 +853,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let principal_trait_ref = principal.with_self_ty(tcx, self_ty); self.walk_vtable(principal_trait_ref, |ecx, assumption, vtable_base, _| { match G::consider_object_bound_candidate(ecx, goal, assumption.to_predicate(tcx)) { + // FIXME: We could skip auto traits here, since they're eagerly elaborated in + // . Ok(result) => candidates.push(Candidate { source: CandidateSource::BuiltinImpl(BuiltinImplSource::Object { vtable_base, diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs index 98f1558b7ffe1..a1c027b8b8262 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs @@ -12,8 +12,11 @@ auto trait Marker2 {} trait Object: Marker1 {} // A supertrait marker is illegal... -impl !Marker1 for dyn Object + Marker2 {} //~ ERROR E0371 - //~^ ERROR 0321 +impl !Marker1 for dyn Object + Marker2 {} +//~^ ERROR E0371 +//~| ERROR E0321 +//~| ERROR E0371 + // ...and also a direct component. impl !Marker2 for dyn Object + Marker2 {} //~ ERROR E0371 //~^ ERROR 0321 diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index ea38afc40ce80..da27498a4b9c7 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -1,10 +1,18 @@ -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` +error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | LL | impl !Marker1 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1` -error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` +error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 + | +LL | impl !Marker1 for dyn Object + Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | LL | impl !Marker1 for dyn Object + Marker2 {} @@ -12,22 +20,22 @@ LL | impl !Marker1 for dyn Object + Marker2 {} | = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1 +error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:21:1 | LL | impl !Marker2 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker2` -error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1 +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:21:1 | LL | impl !Marker2 for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds -error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1 +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:29:1 | LL | impl !Marker2 for dyn Object {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +43,7 @@ LL | impl !Marker2 for dyn Object {} = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:22:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:25:1 | LL | impl !Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^----------- @@ -45,27 +53,27 @@ LL | impl !Send for dyn Marker2 {} | = note: define and implement a trait or new type instead -error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:27:1 +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)` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:30:1 | LL | impl !Send for dyn Object {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type -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)` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:28:1 +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)` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:31:1 | LL | impl !Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:32:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:35:1 | LL | impl !Marker3 for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0117, E0321, E0371. For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs index db2e2b4509a2a..89ccfdb0c54d1 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs @@ -12,8 +12,10 @@ auto trait Marker2 {} trait Object: Marker1 {} // A supertrait marker is illegal... -impl Marker1 for dyn Object + Marker2 {} //~ ERROR E0371 - //~^ ERROR E0321 +impl Marker1 for dyn Object + Marker2 {} +//~^ ERROR E0371 +//~| ERROR E0321 +//~| ERROR E0371 // ...and also a direct component. impl Marker2 for dyn Object + Marker2 {} //~ ERROR E0371 //~^ ERROR E0321 diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr index 2a8713bc32794..482809c6fa1be 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -1,10 +1,18 @@ -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` +error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 | LL | impl Marker1 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1` -error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` +error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 + | +LL | impl Marker1 for dyn Object + Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 | LL | impl Marker1 for dyn Object + Marker2 {} @@ -12,22 +20,22 @@ LL | impl Marker1 for dyn Object + Marker2 {} | = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1 +error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:20:1 | LL | impl Marker2 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker2` -error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1 +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:20:1 | LL | impl Marker2 for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds -error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1 +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:28:1 | LL | impl Marker2 for dyn Object {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +43,7 @@ LL | impl Marker2 for dyn Object {} = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:22:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:24:1 | LL | unsafe impl Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^----------- @@ -45,27 +53,27 @@ LL | unsafe impl Send for dyn Marker2 {} | = note: define and implement a trait or new type instead -error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:27:1 +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)` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:29:1 | LL | unsafe impl Send for dyn Object {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type -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)` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:28:1 +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)` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:30:1 | LL | unsafe impl Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:32:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:34:1 | LL | impl Marker3 for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0117, E0321, E0371. For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.rs b/tests/ui/traits/trait-upcasting/subtrait-method.rs index 20277280440c5..49ba99461f8b5 100644 --- a/tests/ui/traits/trait-upcasting/subtrait-method.rs +++ b/tests/ui/traits/trait-upcasting/subtrait-method.rs @@ -51,17 +51,17 @@ fn main() { let bar: &dyn Bar = baz; bar.c(); - //~^ ERROR no method named `c` found for reference `&dyn Bar` in the current scope [E0599] + //~^ ERROR no method named `c` found for reference `&dyn Bar + Send + Sync` in the current scope [E0599] let foo: &dyn Foo = baz; foo.b(); - //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599] + //~^ ERROR no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599] foo.c(); - //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599] + //~^ ERROR no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599] let foo: &dyn Foo = bar; foo.b(); - //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599] + //~^ ERROR no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599] foo.c(); - //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599] + //~^ ERROR no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599] } diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.stderr b/tests/ui/traits/trait-upcasting/subtrait-method.stderr index 3fdf3f4816160..cd69c17f0d8b2 100644 --- a/tests/ui/traits/trait-upcasting/subtrait-method.stderr +++ b/tests/ui/traits/trait-upcasting/subtrait-method.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope +error[E0599]: no method named `c` found for reference `&dyn Bar + Send + Sync` in the current scope --> $DIR/subtrait-method.rs:53:9 | LL | bar.c(); @@ -11,7 +11,7 @@ note: `Baz` defines an item `c`, perhaps you need to implement it LL | trait Baz: Bar { | ^^^^^^^^^^^^^^ -error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope +error[E0599]: no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope --> $DIR/subtrait-method.rs:57:9 | LL | foo.b(); @@ -24,7 +24,7 @@ note: `Bar` defines an item `b`, perhaps you need to implement it LL | trait Bar: Foo { | ^^^^^^^^^^^^^^ -error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope +error[E0599]: no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope --> $DIR/subtrait-method.rs:59:9 | LL | foo.c(); @@ -37,7 +37,7 @@ note: `Baz` defines an item `c`, perhaps you need to implement it LL | trait Baz: Bar { | ^^^^^^^^^^^^^^ -error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope +error[E0599]: no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope --> $DIR/subtrait-method.rs:63:9 | LL | foo.b(); @@ -50,7 +50,7 @@ note: `Bar` defines an item `b`, perhaps you need to implement it LL | trait Bar: Foo { | ^^^^^^^^^^^^^^ -error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope +error[E0599]: no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope --> $DIR/subtrait-method.rs:65:9 | LL | foo.c(); From caeda851e35474338ad6a35ac3cff0663d653ca9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 10 Jan 2024 18:04:19 +0000 Subject: [PATCH 2/3] Deduplicate implied supertraits for pretty printing --- compiler/rustc_middle/src/ty/print/pretty.rs | 13 +++++++++++ ...mpl-trait-for-marker-trait-negative.stderr | 22 +++++++++---------- ...mpl-trait-for-marker-trait-positive.stderr | 22 +++++++++---------- .../traits/trait-upcasting/subtrait-method.rs | 10 ++++----- .../trait-upcasting/subtrait-method.stderr | 10 ++++----- 5 files changed, 45 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index a10bdc6012c07..d6fbbbb9b22ea 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1293,6 +1293,19 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // FIXME(eddyb) avoid printing twice (needed to ensure // that the auto traits are sorted *and* printed via cx). let mut auto_traits: Vec<_> = predicates.auto_traits().collect(); + let principal_super_traits: FxHashSet<_> = predicates + .principal() + .into_iter() + .flat_map(|principal| { + supertraits_for_pretty_printing( + self.tcx(), + principal.with_self_ty(self.tcx(), self.tcx().types.trait_object_dummy_self), + ) + .map(|trait_ref| trait_ref.def_id()) + }) + .collect(); + + auto_traits.retain(|def_id| !principal_super_traits.contains(def_id)); // The auto traits come ordered by `DefPathHash`. While // `DefPathHash` is *stable* in the sense that it depends on diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index da27498a4b9c7..90c30b5e19b2f 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -1,18 +1,18 @@ -error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1` +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | LL | impl !Marker1 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` -error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1` +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | LL | impl !Marker1 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)` +error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | LL | impl !Marker1 for dyn Object + Marker2 {} @@ -20,13 +20,13 @@ LL | impl !Marker1 for dyn Object + Marker2 {} | = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds -error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker2` +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:21:1 | LL | impl !Marker2 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker2` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` -error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)` +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:21:1 | LL | impl !Marker2 for dyn Object + Marker2 {} @@ -34,7 +34,7 @@ LL | impl !Marker2 for dyn Object + Marker2 {} | = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds -error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + 'static)` +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:29:1 | LL | impl !Marker2 for dyn Object {} @@ -53,13 +53,13 @@ LL | impl !Send for dyn Marker2 {} | = note: define and implement a trait or new type instead -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)` +error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:30:1 | LL | impl !Send for dyn Object {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type -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)` +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)` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:31:1 | LL | impl !Send for dyn Object + Marker2 {} diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr index 482809c6fa1be..6f17be6880f25 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -1,18 +1,18 @@ -error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1` +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 | LL | impl Marker1 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` -error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker1` +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 | LL | impl Marker1 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)` +error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 | LL | impl Marker1 for dyn Object + Marker2 {} @@ -20,13 +20,13 @@ LL | impl Marker1 for dyn Object + Marker2 {} | = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds -error[E0371]: the object type `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements the trait `Marker2` +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:20:1 | LL | impl Marker2 for dyn Object + Marker2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker1 + Marker2 + 'static)` automatically implements trait `Marker2` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` -error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + Marker2 + 'static)` +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:20:1 | LL | impl Marker2 for dyn Object + Marker2 {} @@ -34,7 +34,7 @@ LL | impl Marker2 for dyn Object + Marker2 {} | = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds -error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker1 + 'static)` +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:28:1 | LL | impl Marker2 for dyn Object {} @@ -53,13 +53,13 @@ LL | unsafe impl Send for dyn Marker2 {} | = note: define and implement a trait or new type instead -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)` +error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:29:1 | LL | unsafe impl Send for dyn Object {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type -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)` +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)` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:30:1 | LL | unsafe impl Send for dyn Object + Marker2 {} diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.rs b/tests/ui/traits/trait-upcasting/subtrait-method.rs index 49ba99461f8b5..20277280440c5 100644 --- a/tests/ui/traits/trait-upcasting/subtrait-method.rs +++ b/tests/ui/traits/trait-upcasting/subtrait-method.rs @@ -51,17 +51,17 @@ fn main() { let bar: &dyn Bar = baz; bar.c(); - //~^ ERROR no method named `c` found for reference `&dyn Bar + Send + Sync` in the current scope [E0599] + //~^ ERROR no method named `c` found for reference `&dyn Bar` in the current scope [E0599] let foo: &dyn Foo = baz; foo.b(); - //~^ ERROR no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599] + //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599] foo.c(); - //~^ ERROR no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599] + //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599] let foo: &dyn Foo = bar; foo.b(); - //~^ ERROR no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599] + //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599] foo.c(); - //~^ ERROR no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope [E0599] + //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599] } diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.stderr b/tests/ui/traits/trait-upcasting/subtrait-method.stderr index cd69c17f0d8b2..3fdf3f4816160 100644 --- a/tests/ui/traits/trait-upcasting/subtrait-method.stderr +++ b/tests/ui/traits/trait-upcasting/subtrait-method.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `c` found for reference `&dyn Bar + Send + Sync` in the current scope +error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope --> $DIR/subtrait-method.rs:53:9 | LL | bar.c(); @@ -11,7 +11,7 @@ note: `Baz` defines an item `c`, perhaps you need to implement it LL | trait Baz: Bar { | ^^^^^^^^^^^^^^ -error[E0599]: no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope +error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope --> $DIR/subtrait-method.rs:57:9 | LL | foo.b(); @@ -24,7 +24,7 @@ note: `Bar` defines an item `b`, perhaps you need to implement it LL | trait Bar: Foo { | ^^^^^^^^^^^^^^ -error[E0599]: no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope +error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope --> $DIR/subtrait-method.rs:59:9 | LL | foo.c(); @@ -37,7 +37,7 @@ note: `Baz` defines an item `c`, perhaps you need to implement it LL | trait Baz: Bar { | ^^^^^^^^^^^^^^ -error[E0599]: no method named `b` found for reference `&dyn Foo + Send + Sync` in the current scope +error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope --> $DIR/subtrait-method.rs:63:9 | LL | foo.b(); @@ -50,7 +50,7 @@ note: `Bar` defines an item `b`, perhaps you need to implement it LL | trait Bar: Foo { | ^^^^^^^^^^^^^^ -error[E0599]: no method named `c` found for reference `&dyn Foo + Send + Sync` in the current scope +error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope --> $DIR/subtrait-method.rs:65:9 | LL | foo.c(); From dca631cba2c0698a24a328af1d12ca1fb3dad372 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 10 Jan 2024 18:30:52 +0000 Subject: [PATCH 3/3] Add tests --- .../object/coherence-with-implied-auto-traits.rs | 9 +++++++++ .../coherence-with-implied-auto-traits.stderr | 11 +++++++++++ .../object/upcasting-with-implied-auto-traits.rs | 13 +++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 tests/ui/traits/object/coherence-with-implied-auto-traits.rs create mode 100644 tests/ui/traits/object/coherence-with-implied-auto-traits.stderr create mode 100644 tests/ui/traits/object/upcasting-with-implied-auto-traits.rs diff --git a/tests/ui/traits/object/coherence-with-implied-auto-traits.rs b/tests/ui/traits/object/coherence-with-implied-auto-traits.rs new file mode 100644 index 0000000000000..52cf27aca6d12 --- /dev/null +++ b/tests/ui/traits/object/coherence-with-implied-auto-traits.rs @@ -0,0 +1,9 @@ +trait Foo: Send {} + +trait Bar {} + +impl Bar for dyn Foo {} +impl Bar for dyn Foo + Send {} +//~^ ERROR conflicting implementations of trait `Bar` for type `(dyn Foo + 'static)` + +fn main() {} diff --git a/tests/ui/traits/object/coherence-with-implied-auto-traits.stderr b/tests/ui/traits/object/coherence-with-implied-auto-traits.stderr new file mode 100644 index 0000000000000..f874252d51e41 --- /dev/null +++ b/tests/ui/traits/object/coherence-with-implied-auto-traits.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `Bar` for type `(dyn Foo + 'static)` + --> $DIR/coherence-with-implied-auto-traits.rs:6:1 + | +LL | impl Bar for dyn Foo {} + | -------------------- first implementation here +LL | impl Bar for dyn Foo + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Foo + 'static)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/object/upcasting-with-implied-auto-traits.rs b/tests/ui/traits/object/upcasting-with-implied-auto-traits.rs new file mode 100644 index 0000000000000..9db985237124e --- /dev/null +++ b/tests/ui/traits/object/upcasting-with-implied-auto-traits.rs @@ -0,0 +1,13 @@ +// check-pass +// revisions: current next +//[next] compile-flags: -Znext-solver + +trait Target {} +trait Source: Send + Target {} + +fn upcast(x: &dyn Source) -> &(dyn Target + Send) { x } + +fn same(x: &dyn Source) -> &(dyn Source + Send) { x } +// ^ This isn't upcasting, just passing dyn through unchanged. + +fn main() {}