Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

forbid manually impl'ing one of an object type's marker traits #57352

Merged
merged 2 commits into from
Jan 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/librustc_typeck/coherence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,23 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI
// This is something like impl Trait1 for Trait2. Illegal
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.

if let Some(principal_def_id) = data.principal_def_id() {
if !tcx.is_object_safe(principal_def_id) {
let component_def_ids = data.iter().flat_map(|predicate| {
match predicate.skip_binder() {
ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id),
ty::ExistentialPredicate::AutoTrait(def_id) => Some(*def_id),
// An associated type projection necessarily comes with
// an additional `Trait` requirement.
ty::ExistentialPredicate::Projection(..) => None,
}
});

for component_def_id in component_def_ids {
if !tcx.is_object_safe(component_def_id) {
// This is an error, but it will be reported by wfcheck. Ignore it here.
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
} else {
let mut supertrait_def_ids =
traits::supertrait_def_ids(tcx, principal_def_id);
traits::supertrait_def_ids(tcx, component_def_id);
if supertrait_def_ids.any(|d| d == trait_def_id) {
let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
struct_span_err!(tcx.sess,
Expand All @@ -193,6 +203,5 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI
}
}
}
// FIXME: also check auto-trait def-ids? (e.g. `impl Sync for Foo+Sync`)?
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#![feature(optin_builtin_traits)]

// Test for issue #56934 - that it is impossible to redundantly
// implement an auto-trait for a trait object type that contains it.

// Negative impl variant.

auto trait Marker1 {}
auto trait Marker2 {}

trait Object: Marker1 {}

// A supertrait marker is illegal...
impl !Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
// ...and also a direct component.
impl !Marker2 for dyn Object + Marker2 { } //~ ERROR E0371

// But implementing a marker if it is not present is OK.
impl !Marker2 for dyn Object {} // OK

// A non-principal trait-object type is orphan even in its crate.
impl !Send for dyn Marker2 {} //~ ERROR E0117

// And impl'ing a remote marker for a local trait object is forbidden
// by one of these special orphan-like rules.
impl !Send for dyn Object {} //~ ERROR E0321
impl !Send for dyn Object + Marker2 {} //~ ERROR E0321

fn main() { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:14:1
|
LL | impl !Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`

error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:16:1
|
LL | impl !Marker2 for dyn Object + Marker2 { } //~ ERROR E0371
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`

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
|
LL | impl !Send for dyn Marker2 {} //~ ERROR E0117
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
= note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead

error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)`
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1
|
LL | impl !Send for dyn Object {} //~ ERROR E0321
| ^^^^^^^^^^^^^^^^^^^^^^^^^ 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 `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)`
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:27:1
|
LL | impl !Send for dyn Object + Marker2 {} //~ ERROR E0321
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type

error: aborting due to 5 previous errors

Some errors occurred: E0117, E0321, E0371.
For more information about an error, try `rustc --explain E0117`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#![feature(optin_builtin_traits)]

// Test for issue #56934 - that it is impossible to redundantly
// implement an auto-trait for a trait object type that contains it.

// Positive impl variant.

auto trait Marker1 {}
auto trait Marker2 {}

trait Object: Marker1 {}

// A supertrait marker is illegal...
impl Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
// ...and also a direct component.
impl Marker2 for dyn Object + Marker2 { } //~ ERROR E0371

// But implementing a marker if it is not present is OK.
impl Marker2 for dyn Object {} // OK

// A non-principal trait-object type is orphan even in its crate.
unsafe impl Send for dyn Marker2 {} //~ ERROR E0117

// And impl'ing a remote marker for a local trait object is forbidden
// by one of these special orphan-like rules.
unsafe impl Send for dyn Object {} //~ ERROR E0321
unsafe impl Send for dyn Object + Marker2 {} //~ ERROR E0321

fn main() { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:14:1
|
LL | impl Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`

error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:16:1
|
LL | impl Marker2 for dyn Object + Marker2 { } //~ ERROR E0371
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`

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
|
LL | unsafe impl Send for dyn Marker2 {} //~ ERROR E0117
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
= note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead

error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)`
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1
|
LL | unsafe impl Send for dyn Object {} //~ ERROR E0321
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)`
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:27:1
|
LL | unsafe impl Send for dyn Object + Marker2 {} //~ ERROR E0321
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type

error: aborting due to 5 previous errors

Some errors occurred: E0117, E0321, E0371.
For more information about an error, try `rustc --explain E0117`.