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

Allow more !Copy impls #101875

Merged
merged 1 commit into from
Sep 26, 2022
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
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