Skip to content

Commit

Permalink
Rollup merge of #101875 - fmease:allow-more-negative-copy-impls, r=lcnr
Browse files Browse the repository at this point in the history
Allow more `!Copy` impls

You can already implement `!Copy` for a lot of types (with `#![feature(negative_impls)]`). However, before this PR you could not implement `!Copy` for ADTs whose fields don't implement `Copy` which didn't make any sense. Further, you couldn't implement `!Copy` for types impl'ing `Drop` (equally nonsensical).

``@rustbot`` label T-types F-negative_impls
Fixes #101836.

r? types
  • Loading branch information
matthiaskrgr authored Sep 26, 2022
2 parents e1d7dec + 28e0c5a commit 4d4a369
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 30 deletions.
18 changes: 6 additions & 12 deletions compiler/rustc_typeck/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,21 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
let self_type = tcx.type_of(impl_did);
debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);

let span = tcx.hir().span(impl_hir_id);
let param_env = tcx.param_env(impl_did);
assert!(!self_type.has_escaping_bound_vars());

debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);

let span = match tcx.hir().expect_item(impl_did).kind {
ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. }) => return,
ItemKind::Impl(impl_) => impl_.self_ty.span,
_ => bug!("expected Copy impl item"),
};

let cause = traits::ObligationCause::misc(span, impl_hir_id);
match can_type_implement_copy(tcx, param_env, self_type, cause) {
Ok(()) => {}
Err(CopyImplementationError::InfrigingFields(fields)) => {
let item = tcx.hir().expect_item(impl_did);
let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind {
tr.path.span
} else {
span
};

let mut err = struct_span_err!(
tcx.sess,
span,
Expand Down Expand Up @@ -166,10 +164,6 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
err.emit();
}
Err(CopyImplementationError::NotAnAdt) => {
let item = tcx.hir().expect_item(impl_did);
let span =
if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span };

tcx.sess.emit_err(CopyImplOnNonAdt { span });
}
Err(CopyImplementationError::HasDestructor) => {
Expand Down
11 changes: 11 additions & 0 deletions src/test/ui/coherence/coherence-negative-impls-copy-bad.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![feature(negative_impls)]
#![crate_type = "lib"]

impl !Copy for str {}
//~^ ERROR only traits defined in the current crate can be implemented

impl !Copy for fn() {}
//~^ ERROR only traits defined in the current crate can be implemented

impl !Copy for () {}
//~^ ERROR only traits defined in the current crate can be implemented
36 changes: 36 additions & 0 deletions src/test/ui/coherence/coherence-negative-impls-copy-bad.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> $DIR/coherence-negative-impls-copy-bad.rs:4:1
|
LL | impl !Copy for str {}
| ^^^^^^^^^^^^^^^---
| | |
| | `str` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> $DIR/coherence-negative-impls-copy-bad.rs:7:1
|
LL | impl !Copy for fn() {}
| ^^^^^^^^^^^^^^^----
| | |
| | `fn()` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> $DIR/coherence-negative-impls-copy-bad.rs:10:1
|
LL | impl !Copy for () {}
| ^^^^^^^^^^^^^^^--
| | |
| | this is not defined in the current crate because tuples are always foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0117`.
29 changes: 29 additions & 0 deletions src/test/ui/coherence/coherence-negative-impls-copy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// check-pass
// regression test for issue #101836

#![feature(negative_impls, extern_types)]
#![crate_type = "lib"]

struct NonCopy;
struct NeverCopy(NonCopy);

impl !Copy for NeverCopy {}


struct WithDrop;
impl Drop for WithDrop { fn drop(&mut self) {} }

impl !Copy for WithDrop {}


struct Type;
trait Trait {}
extern {
type ExternType;
}

impl !Copy for &mut Type {}

impl !Copy for dyn Trait {}

impl !Copy for ExternType {}
4 changes: 2 additions & 2 deletions src/test/ui/coherence/deep-bad-copy-reason.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/deep-bad-copy-reason.rs:33:15
--> $DIR/deep-bad-copy-reason.rs:33:24
|
LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>);
| ------------------------ this field does not implement `Copy`
...
LL | impl<'tcx, T> Copy for List<'tcx, T> {}
| ^^^^
| ^^^^^^^^^^^^^
|
note: the `Copy` impl for `Interned<'tcx, ListS<T>>` requires that `OpaqueListContents: Sized`
--> $DIR/deep-bad-copy-reason.rs:23:26
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/opt-in-copy.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/opt-in-copy.rs:7:6
--> $DIR/opt-in-copy.rs:7:15
|
LL | but_i_cant: CantCopyThis,
| ------------------------ this field does not implement `Copy`
...
LL | impl Copy for IWantToCopyThis {}
| ^^^^
| ^^^^^^^^^^^^^^^

error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/opt-in-copy.rs:19:6
--> $DIR/opt-in-copy.rs:19:15
|
LL | ButICant(CantCopyThisEither),
| ------------------ this field does not implement `Copy`
...
LL | impl Copy for IWantToCopyThisToo {}
| ^^^^
| ^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/span/E0204.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/E0204.rs:5:6
--> $DIR/E0204.rs:5:15
|
LL | foo: Vec<u32>,
| ------------- this field does not implement `Copy`
...
LL | impl Copy for Foo { }
| ^^^^
| ^^^

error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/E0204.rs:7:10
Expand All @@ -19,13 +19,13 @@ LL | ty: &'a mut bool,
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/E0204.rs:17:6
--> $DIR/E0204.rs:17:15
|
LL | Bar { x: Vec<u32> },
| ----------- this field does not implement `Copy`
...
LL | impl Copy for EFoo { }
| ^^^^
| ^^^^

error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/E0204.rs:19:10
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:9
--> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:18
|
LL | struct Wrapper<T>(T);
| - this field does not implement `Copy`
...
LL | impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
| ^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Display`
--> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/missing-bound-in-manual-copy-impl.rs:6:9
--> $DIR/missing-bound-in-manual-copy-impl.rs:6:18
|
LL | struct Wrapper<T>(T);
| - this field does not implement `Copy`
LL |
LL | impl<S> Copy for Wrapper<S> {}
| ^^^^
| ^^^^^^^^^^
|
help: consider restricting type parameter `S`
|
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/traits/copy-impl-cannot-normalize.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `T: TraitFoo` is not satisfied
--> $DIR/copy-impl-cannot-normalize.rs:22:1
--> $DIR/copy-impl-cannot-normalize.rs:22:18
|
LL | impl<T> Copy for Foo<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitFoo` is not implemented for `T`
| ^^^^^^ the trait `TraitFoo` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/union/union-copy.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/union-copy.rs:12:6
--> $DIR/union-copy.rs:12:15
|
LL | a: std::mem::ManuallyDrop<String>
| --------------------------------- this field does not implement `Copy`
...
LL | impl Copy for W {}
| ^^^^
| ^
|
note: the `Copy` impl for `ManuallyDrop<String>` requires that `String: Copy`
--> $DIR/union-copy.rs:8:8
Expand Down

0 comments on commit 4d4a369

Please sign in to comment.