Skip to content

improve some Drop-related error messages #67823

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

Merged
merged 2 commits into from
Jan 4, 2020
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
34 changes: 18 additions & 16 deletions src/librustc_typeck/check/dropck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro

ensure_drop_predicates_are_implied_by_item_defn(
tcx,
drop_impl_did,
dtor_predicates,
adt_def.did,
self_to_impl_substs,
Expand Down Expand Up @@ -95,16 +94,23 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
}
Err(_) => {
let item_span = tcx.def_span(self_type_did);
let self_descr = tcx
.def_kind(self_type_did)
.map(|kind| kind.descr(self_type_did))
.unwrap_or("type");
struct_span_err!(
tcx.sess,
drop_impl_span,
E0366,
"Implementations of Drop cannot be specialized"
"`Drop` impls cannot be specialized"
)
.span_note(
item_span,
"Use same sequence of generic type and region \
parameters that is on the struct/enum definition",
&format!(
"use the same sequence of generic type, lifetime and const parameters \
as the {} definition",
self_descr,
),
)
.emit();
return Err(ErrorReported);
Expand Down Expand Up @@ -143,7 +149,6 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
/// implied by assuming the predicates attached to self_type_did.
fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
tcx: TyCtxt<'tcx>,
drop_impl_did: DefId,
dtor_predicates: ty::GenericPredicates<'tcx>,
self_type_did: DefId,
self_to_impl_substs: SubstsRef<'tcx>,
Expand Down Expand Up @@ -187,8 +192,6 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(

let self_type_hir_id = tcx.hir().as_local_hir_id(self_type_did).unwrap();

let drop_impl_span = tcx.def_span(drop_impl_did);

// We can assume the predicates attached to struct/enum definition
// hold.
let generic_assumptions = tcx.predicates_of(self_type_did);
Expand All @@ -205,7 +208,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// just to look for all the predicates directly.

assert_eq!(dtor_predicates.parent, None);
for (predicate, _) in dtor_predicates.predicates {
for (predicate, predicate_sp) in dtor_predicates.predicates {
// (We do not need to worry about deep analysis of type
// expressions etc because the Drop impls are already forced
// to take on a structure that is roughly an alpha-renaming of
Expand Down Expand Up @@ -241,18 +244,17 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(

if !assumptions_in_impl_context.iter().any(predicate_matches_closure) {
let item_span = tcx.hir().span(self_type_hir_id);
let self_descr =
tcx.def_kind(self_type_did).map(|kind| kind.descr(self_type_did)).unwrap_or("type");
struct_span_err!(
tcx.sess,
drop_impl_span,
*predicate_sp,
E0367,
"The requirement `{}` is added only by the Drop impl.",
predicate
)
.span_note(
item_span,
"The same requirement must be part of \
the struct/enum definition",
"`Drop` impl requires `{}` but the {} it is implemented for does not",
predicate,
self_descr,
)
.span_note(item_span, "the implementor must specify the same requirement")
.emit();
result = Err(ErrorReported);
}
Expand Down
47 changes: 18 additions & 29 deletions src/librustc_typeck/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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) {
Expand Down
7 changes: 6 additions & 1 deletion src/test/ui/dropck/drop-on-non-struct.rs
Original file line number Diff line number Diff line change
@@ -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() {
}
14 changes: 10 additions & 4 deletions src/test/ui/dropck/drop-on-non-struct.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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`.
3 changes: 1 addition & 2 deletions src/test/ui/error-codes/E0117.rs
Original file line number Diff line number Diff line change
@@ -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() {
}
4 changes: 2 additions & 2 deletions src/test/ui/error-codes/E0117.stderr
Original file line number Diff line number Diff line change
@@ -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
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 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

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-17959.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct G<T: ?Sized> {
}

impl<T> Drop for G<T> {
//~^ ERROR: The requirement `T: std::marker::Sized` is added only by the Drop impl. [E0367]
//~^ ERROR `Drop` impl requires `T: std::marker::Sized`
fn drop(&mut self) {
if !self._ptr.is_null() {
}
Expand Down
16 changes: 5 additions & 11 deletions src/test/ui/issues/issue-17959.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
error[E0367]: The requirement `T: std::marker::Sized` is added only by the Drop impl.
--> $DIR/issue-17959.rs:11:1
error[E0367]: `Drop` impl requires `T: std::marker::Sized` but the struct it is implemented for does not
--> $DIR/issue-17959.rs:11:6
|
LL | / impl<T> Drop for G<T> {
LL | |
LL | | fn drop(&mut self) {
LL | | if !self._ptr.is_null() {
LL | | }
LL | | }
LL | | }
| |_^
LL | impl<T> Drop for G<T> {
| ^
|
note: The same requirement must be part of the struct/enum definition
note: the implementor must specify the same requirement
--> $DIR/issue-17959.rs:7:1
|
LL | / struct G<T: ?Sized> {
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-38868.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0366]: Implementations of Drop cannot be specialized
error[E0366]: `Drop` impls cannot be specialized
--> $DIR/issue-38868.rs:5:1
|
LL | / impl Drop for List<i32> {
Expand All @@ -8,7 +8,7 @@ LL | | }
LL | | }
| |_^
|
note: Use same sequence of generic type and region parameters that is on the struct/enum definition
note: use the same sequence of generic type, lifetime and const parameters as the struct definition
--> $DIR/issue-38868.rs:1:1
|
LL | / pub struct List<T> {
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 @@ -9,11 +9,11 @@ LL | impl<T> 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<T> 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<T>`)
--> $DIR/issue-41974.rs:7:6
Expand Down
27 changes: 20 additions & 7 deletions src/test/ui/reject-specialized-drops-8142.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Issue 8142: Test that Drop impls cannot be specialized beyond the
// predicates attached to the struct/enum definition itself.
// predicates attached to the type definition itself.

trait Bound { fn foo(&self) { } }
struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
Expand All @@ -16,12 +16,16 @@ struct U;
struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }

enum Enum<T> { Variant(T) }
struct TupleStruct<T>(T);
union Union<T: Copy> { f: T }

impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT
//~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl.
//~^ ERROR `Drop` impl requires `'adds_bnd : 'al`
fn drop(&mut self) { } }

impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT
//~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl.
//~^ ERROR `Drop` impl requires `'adds_bnd : 'al`
fn drop(&mut self) { } }

impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT
Expand All @@ -34,13 +38,13 @@ impl Drop for N<'static> { fn drop(&mut self) { } } // RE
impl<COkNoBound> Drop for O<COkNoBound> { fn drop(&mut self) { } } // ACCEPT

impl Drop for P<i8> { fn drop(&mut self) { } } // REJECT
//~^ ERROR Implementations of Drop cannot be specialized
//~^ ERROR `Drop` impls cannot be specialized

impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT
//~^ ERROR The requirement `AddsBnd: Bound` is added only by the Drop impl.
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`

impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT
//~^ ERROR The requirement `AddsRBnd : 'rbnd` is added only by the Drop impl.
//~^ ERROR `Drop` impl requires `AddsRBnd : 'rbnd`

impl<Bs:Bound> Drop for S<Bs> { fn drop(&mut self) { } } // ACCEPT

Expand All @@ -49,9 +53,18 @@ impl<'t,Bt:'t> Drop for T<'t,Bt> { fn drop(&mut self) { } } // ACCEPT
impl Drop for U { fn drop(&mut self) { } } // ACCEPT

impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT
//~^ ERROR Implementations of Drop cannot be specialized
//~^ ERROR `Drop` impls cannot be specialized

impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw`

impl<AddsBnd:Bound> Drop for Enum<AddsBnd> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`

impl<AddsBnd:Bound> Drop for TupleStruct<AddsBnd> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`

impl<AddsBnd:Copy + Bound> Drop for Union<AddsBnd> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`

pub fn main() { }
Loading