diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 7f7e21838d2..7e016cf7e9a 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -13,7 +13,6 @@ use rustc::ty::util::CopyImplementationError; use rustc::ty::TypeFoldable; use rustc::ty::{self, Ty, TyCtxt}; -use hir::Node; use rustc::hir::def_id::DefId; use rustc::hir::{self, ItemKind}; @@ -51,35 +50,25 @@ impl<'tcx> Checker<'tcx> { } fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: DefId) { - if let ty::Adt(..) = tcx.type_of(impl_did).kind { - /* do nothing */ - } else { - // Destructors only work on nominal types. - if let Some(impl_hir_id) = tcx.hir().as_local_hir_id(impl_did) { - if let Some(Node::Item(item)) = tcx.hir().find(impl_hir_id) { - let span = match item.kind { - ItemKind::Impl(.., ref ty, _) => ty.span, - _ => item.span, - }; - struct_span_err!( - tcx.sess, - span, - E0120, - "the Drop trait may only be implemented on \ - structures" - ) - .span_label(span, "implementing Drop requires a struct") - .emit(); - } else { - bug!("didn't find impl in ast map"); - } - } else { - bug!( - "found external impl of Drop trait on \ - something other than a struct" - ); - } + // Destructors only work on nominal types. + if let ty::Adt(..) | ty::Error = tcx.type_of(impl_did).kind { + return; } + + let impl_hir_id = tcx.hir().as_local_hir_id(impl_did).expect("foreign Drop impl on non-ADT"); + let sp = match tcx.hir().expect_item(impl_hir_id).kind { + ItemKind::Impl(.., ty, _) => ty.span, + _ => bug!("expected Drop impl item"), + }; + + struct_span_err!( + tcx.sess, + sp, + E0120, + "the `Drop` trait may only be implemented for structs, enums, and unions", + ) + .span_label(sp, "must be a struct, enum, or union") + .emit(); } fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: DefId) { diff --git a/src/test/ui/dropck/drop-on-non-struct.rs b/src/test/ui/dropck/drop-on-non-struct.rs index 259cdf40ae5..ef5e18126dc 100644 --- a/src/test/ui/dropck/drop-on-non-struct.rs +++ b/src/test/ui/dropck/drop-on-non-struct.rs @@ -1,10 +1,15 @@ impl<'a> Drop for &'a mut isize { - //~^ ERROR the Drop trait may only be implemented on structures + //~^ ERROR the `Drop` trait may only be implemented for structs, enums, and unions //~^^ ERROR E0117 fn drop(&mut self) { println!("kaboom"); } } +impl Drop for Nonexistent { + //~^ ERROR cannot find type `Nonexistent` + fn drop(&mut self) { } +} + 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 a374b0d2636..3991c44f2ed 100644 --- a/src/test/ui/dropck/drop-on-non-struct.stderr +++ b/src/test/ui/dropck/drop-on-non-struct.stderr @@ -1,8 +1,14 @@ -error[E0120]: the Drop trait may only be implemented on structures +error[E0412]: cannot find type `Nonexistent` in this scope + --> $DIR/drop-on-non-struct.rs:9:15 + | +LL | impl Drop for Nonexistent { + | ^^^^^^^^^^^ not found in this scope + +error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions --> $DIR/drop-on-non-struct.rs:1:19 | LL | impl<'a> Drop for &'a mut isize { - | ^^^^^^^^^^^^^ implementing Drop requires a struct + | ^^^^^^^^^^^^^ must be a struct, enum, or union error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/drop-on-non-struct.rs:1:1 @@ -15,7 +21,7 @@ LL | impl<'a> Drop for &'a mut isize { | = note: define and implement a trait or new type instead -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0117, E0120. +Some errors have detailed explanations: E0117, E0120, E0412. For more information about an error, try `rustc --explain E0117`. diff --git a/src/test/ui/error-codes/E0117.rs b/src/test/ui/error-codes/E0117.rs index 18dd809f3ff..dbbac514801 100644 --- a/src/test/ui/error-codes/E0117.rs +++ b/src/test/ui/error-codes/E0117.rs @@ -1,6 +1,5 @@ impl Drop for u32 {} //~ ERROR E0117 -//~| ERROR the Drop trait may only be implemented on structures -//~| implementing Drop requires a struct +//~| ERROR the `Drop` trait may only be implemented for 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 f0cfc8a2533..b48a1d8e50d 100644 --- a/src/test/ui/error-codes/E0117.stderr +++ b/src/test/ui/error-codes/E0117.stderr @@ -1,8 +1,8 @@ -error[E0120]: the Drop trait may only be implemented on structures +error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions --> $DIR/E0117.rs:1:15 | LL | impl Drop for u32 {} - | ^^^ implementing Drop requires a struct + | ^^^ must be a struct, enum, or union error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/E0117.rs:1:1 diff --git a/src/test/ui/error-codes/E0120.stderr b/src/test/ui/error-codes/E0120.stderr index 68ca7d800d5..6c306455e42 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 on structures +error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions --> $DIR/E0120.rs:3:15 | LL | impl Drop for dyn MyTrait { - | ^^^^^^^^^^^ implementing Drop requires a struct + | ^^^^^^^^^^^ must be a struct, enum, or union 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 9f164822dea..d082e0a6b5d 100644 --- a/src/test/ui/issues/issue-41974.stderr +++ b/src/test/ui/issues/issue-41974.stderr @@ -9,11 +9,11 @@ LL | impl Drop for T where T: A { where T: ?Sized; = note: downstream crates may implement trait `A` for type `std::boxed::Box<_>` -error[E0120]: the Drop trait may only be implemented on structures +error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions --> $DIR/issue-41974.rs:7:18 | LL | impl Drop for T where T: A { - | ^ implementing Drop requires a struct + | ^ must be a struct, enum, or union error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) --> $DIR/issue-41974.rs:7:6