Skip to content

Commit

Permalink
Rollup merge of #99576 - compiler-errors:foreign-fundamental-drop-is-…
Browse files Browse the repository at this point in the history
…bad, r=TaKO8Ki

Do not allow `Drop` impl on foreign fundamental types

`Drop` should not be implemented on `Pin<T>` even if `T` is local.

This does not trigger regular orphan rules is because `Pin` is `#[fundamental]`... but we don't allow specialized `Drop` impls anyways, so these rules are not sufficient to prevent this impl on stable. Let's just choose even stricter rules, since we shouldn't be implementing `Drop` on a foreign ADT ever.

Fixes #99575
  • Loading branch information
Dylan-DPC committed Aug 19, 2022
2 parents 6c943ba + fd934c9 commit 0788442
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 18 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_error_messages/locales/en-US/typeck.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_typeck/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
23 changes: 23 additions & 0 deletions src/test/ui/drop/drop-foreign-fundamental.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::ops::Deref;
use std::pin::Pin;

struct Whatever<T>(T);

impl<T> Deref for Whatever<T> {
type Target = T;

fn deref(&self) -> &T {
&self.0
}
}

struct A;

impl Drop for Pin<Whatever<A>> {
//~^ 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));
}
9 changes: 9 additions & 0 deletions src/test/ui/drop/drop-foreign-fundamental.stderr
Original file line number Diff line number Diff line change
@@ -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<Whatever<A>> {
| ^^^^^^^^^^^^^^^^ 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`.
7 changes: 3 additions & 4 deletions src/test/ui/dropck/drop-on-non-struct.rs
Original file line number Diff line number Diff line change
@@ -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");
Expand All @@ -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() {}
4 changes: 2 additions & 2 deletions src/test/ui/dropck/drop-on-non-struct.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0117.rs
Original file line number Diff line number Diff line change
@@ -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() {}
4 changes: 2 additions & 2 deletions src/test/ui/error-codes/E0117.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/error-codes/E0120.stderr
Original file line number Diff line number Diff line change
@@ -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

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-41974.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ LL | impl<T> 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<T> 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

Expand Down

0 comments on commit 0788442

Please sign in to comment.