From fd934c99bcf1a930ef44a27129ef24b323d3c54f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Jul 2022 22:00:15 +0000 Subject: [PATCH] Do not allow Drop impl on foreign fundamental types --- .../locales/en-US/typeck.ftl | 4 ++-- .../rustc_typeck/src/coherence/builtin.rs | 8 ++++--- src/test/ui/drop/drop-foreign-fundamental.rs | 23 +++++++++++++++++++ .../ui/drop/drop-foreign-fundamental.stderr | 9 ++++++++ src/test/ui/dropck/drop-on-non-struct.rs | 7 +++--- src/test/ui/dropck/drop-on-non-struct.stderr | 4 ++-- src/test/ui/error-codes/E0117.rs | 2 +- src/test/ui/error-codes/E0117.stderr | 4 ++-- src/test/ui/error-codes/E0120.stderr | 4 ++-- src/test/ui/issues/issue-41974.stderr | 4 ++-- 10 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/drop/drop-foreign-fundamental.rs create mode 100644 src/test/ui/drop/drop-foreign-fundamental.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/typeck.ftl b/compiler/rustc_error_messages/locales/en-US/typeck.ftl index 494b8f91393..2a8488cc548 100644 --- a/compiler/rustc_error_messages/locales/en-US/typeck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/typeck.ftl @@ -24,8 +24,8 @@ typeck_lifetimes_or_bounds_mismatch_on_trait = .generics_label = lifetimes in impl do not match this {$item_kind} in trait typeck_drop_impl_on_wrong_item = - the `Drop` trait may only be implemented for structs, enums, and unions - .label = must be a struct, enum, or union + the `Drop` trait may only be implemented for local structs, enums, and unions + .label = must be a struct, enum, or union in the current crate typeck_field_already_declared = field `{$field_name}` is already declared diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index 043e21fc1e3..2467a81638f 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -47,9 +47,11 @@ impl<'tcx> Checker<'tcx> { } fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) { - // Destructors only work on nominal types. - if let ty::Adt(..) | ty::Error(_) = tcx.type_of(impl_did).kind() { - return; + // Destructors only work on local ADT types. + match tcx.type_of(impl_did).kind() { + ty::Adt(def, _) if def.did().is_local() => return, + ty::Error(_) => return, + _ => {} } let sp = match tcx.hir().expect_item(impl_did).kind { diff --git a/src/test/ui/drop/drop-foreign-fundamental.rs b/src/test/ui/drop/drop-foreign-fundamental.rs new file mode 100644 index 00000000000..c43df40d6c2 --- /dev/null +++ b/src/test/ui/drop/drop-foreign-fundamental.rs @@ -0,0 +1,23 @@ +use std::ops::Deref; +use std::pin::Pin; + +struct Whatever(T); + +impl Deref for Whatever { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +struct A; + +impl Drop for Pin> { + //~^ ERROR the `Drop` trait may only be implemented for local structs, enums, and unions + fn drop(&mut self) {} +} + +fn main() { + let x = Pin::new(Whatever(1.0f32)); +} diff --git a/src/test/ui/drop/drop-foreign-fundamental.stderr b/src/test/ui/drop/drop-foreign-fundamental.stderr new file mode 100644 index 00000000000..fbd1ba08591 --- /dev/null +++ b/src/test/ui/drop/drop-foreign-fundamental.stderr @@ -0,0 +1,9 @@ +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions + --> $DIR/drop-foreign-fundamental.rs:16:15 + | +LL | impl Drop for Pin> { + | ^^^^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0120`. diff --git a/src/test/ui/dropck/drop-on-non-struct.rs b/src/test/ui/dropck/drop-on-non-struct.rs index ef5e18126dc..145eab126c2 100644 --- a/src/test/ui/dropck/drop-on-non-struct.rs +++ b/src/test/ui/dropck/drop-on-non-struct.rs @@ -1,5 +1,5 @@ impl<'a> Drop for &'a mut isize { - //~^ ERROR the `Drop` trait may only be implemented for structs, enums, and unions + //~^ ERROR the `Drop` trait may only be implemented for local structs, enums, and unions //~^^ ERROR E0117 fn drop(&mut self) { println!("kaboom"); @@ -8,8 +8,7 @@ impl<'a> Drop for &'a mut isize { impl Drop for Nonexistent { //~^ ERROR cannot find type `Nonexistent` - fn drop(&mut self) { } + fn drop(&mut self) {} } -fn main() { -} +fn main() {} diff --git a/src/test/ui/dropck/drop-on-non-struct.stderr b/src/test/ui/dropck/drop-on-non-struct.stderr index e52728f3781..e8fbe5e9726 100644 --- a/src/test/ui/dropck/drop-on-non-struct.stderr +++ b/src/test/ui/dropck/drop-on-non-struct.stderr @@ -15,11 +15,11 @@ LL | impl<'a> Drop for &'a mut isize { | = note: define and implement a trait or new type instead -error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions --> $DIR/drop-on-non-struct.rs:1:19 | LL | impl<'a> Drop for &'a mut isize { - | ^^^^^^^^^^^^^ must be a struct, enum, or union + | ^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate error: aborting due to 3 previous errors diff --git a/src/test/ui/error-codes/E0117.rs b/src/test/ui/error-codes/E0117.rs index 22b48657385..406d24e3666 100644 --- a/src/test/ui/error-codes/E0117.rs +++ b/src/test/ui/error-codes/E0117.rs @@ -1,4 +1,4 @@ impl Drop for u32 {} //~ ERROR E0117 -//~| ERROR the `Drop` trait may only be implemented for structs, enums, and unions +//~| ERROR the `Drop` trait may only be implemented for local structs, enums, and unions fn main() {} diff --git a/src/test/ui/error-codes/E0117.stderr b/src/test/ui/error-codes/E0117.stderr index 76d9f5cc0e5..f144aa9f72c 100644 --- a/src/test/ui/error-codes/E0117.stderr +++ b/src/test/ui/error-codes/E0117.stderr @@ -9,11 +9,11 @@ LL | impl Drop for u32 {} | = note: define and implement a trait or new type instead -error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions --> $DIR/E0117.rs:1:15 | LL | impl Drop for u32 {} - | ^^^ must be a struct, enum, or union + | ^^^ must be a struct, enum, or union in the current crate error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0120.stderr b/src/test/ui/error-codes/E0120.stderr index 6c306455e42..75778f1f94a 100644 --- a/src/test/ui/error-codes/E0120.stderr +++ b/src/test/ui/error-codes/E0120.stderr @@ -1,8 +1,8 @@ -error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions --> $DIR/E0120.rs:3:15 | LL | impl Drop for dyn MyTrait { - | ^^^^^^^^^^^ must be a struct, enum, or union + | ^^^^^^^^^^^ must be a struct, enum, or union in the current crate error: aborting due to previous error diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr index fcbb4014025..e249db9df53 100644 --- a/src/test/ui/issues/issue-41974.stderr +++ b/src/test/ui/issues/issue-41974.stderr @@ -7,11 +7,11 @@ LL | impl Drop for T where T: A { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions --> $DIR/issue-41974.rs:7:18 | LL | impl Drop for T where T: A { - | ^ must be a struct, enum, or union + | ^ must be a struct, enum, or union in the current crate error: aborting due to 2 previous errors