diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 52ddacc1c4b1a..4c31363f2c084 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -21,11 +21,29 @@ use rustc_target::spec::abi; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific /// method that is called). -pub fn check_legal_trait_for_method_call(tcx: TyCtxt<'_>, span: Span, trait_id: DefId) { +pub fn check_legal_trait_for_method_call( + tcx: TyCtxt<'_>, + span: Span, + receiver: Option, + trait_id: DefId, +) { if tcx.lang_items().drop_trait() == Some(trait_id) { - struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method") - .span_label(span, "explicit destructor calls not allowed") - .emit(); + let mut err = struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method"); + err.span_label(span, "explicit destructor calls not allowed"); + + let snippet = receiver + .and_then(|s| tcx.sess.source_map().span_to_snippet(s).ok()) + .unwrap_or_default(); + + let (suggestion, applicability) = if snippet.is_empty() { + (snippet, Applicability::Unspecified) + } else { + (format!("drop({})", snippet), Applicability::MachineApplicable) + }; + + err.span_suggestion(span, "consider using `drop` function", suggestion, applicability); + + err.emit(); } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index c4805c54a7d43..38a5bd5fce00d 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -597,9 +597,12 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) { // Disallow calls to the method `drop` defined in the `Drop` trait. match pick.item.container { - ty::TraitContainer(trait_def_id) => { - callee::check_legal_trait_for_method_call(self.tcx, self.span, trait_def_id) - } + ty::TraitContainer(trait_def_id) => callee::check_legal_trait_for_method_call( + self.tcx, + self.span, + Some(self.self_expr.span), + trait_def_id, + ), ty::ImplContainer(..) => {} } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d72c74e4188ee..3ac3934bea32b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5438,7 +5438,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("instantiate_value_path: def_id={:?} container={:?}", def_id, container); match container { ty::TraitContainer(trait_did) => { - callee::check_legal_trait_for_method_call(tcx, span, trait_did) + callee::check_legal_trait_for_method_call(tcx, span, None, trait_did) } ty::ImplContainer(impl_def_id) => { if segments.len() == 1 { diff --git a/src/test/ui/error-codes/E0040.stderr b/src/test/ui/error-codes/E0040.stderr index 966455902817d..69cf28b29704f 100644 --- a/src/test/ui/error-codes/E0040.stderr +++ b/src/test/ui/error-codes/E0040.stderr @@ -2,7 +2,10 @@ error[E0040]: explicit use of destructor method --> $DIR/E0040.rs:13:7 | LL | x.drop(); - | ^^^^ explicit destructor calls not allowed + | ^^^^ + | | + | explicit destructor calls not allowed + | help: consider using `drop` function: `drop(x)` error: aborting due to previous error diff --git a/src/test/ui/explicit/explicit-call-to-dtor.stderr b/src/test/ui/explicit/explicit-call-to-dtor.stderr index cbbe967179ef3..5ebe4ee4b90f8 100644 --- a/src/test/ui/explicit/explicit-call-to-dtor.stderr +++ b/src/test/ui/explicit/explicit-call-to-dtor.stderr @@ -2,7 +2,10 @@ error[E0040]: explicit use of destructor method --> $DIR/explicit-call-to-dtor.rs:13:7 | LL | x.drop(); - | ^^^^ explicit destructor calls not allowed + | ^^^^ + | | + | explicit destructor calls not allowed + | help: consider using `drop` function: `drop(x)` error: aborting due to previous error diff --git a/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr b/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr index 0b302e30b64f3..cd3fb3119a5cf 100644 --- a/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr +++ b/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr @@ -2,7 +2,10 @@ error[E0040]: explicit use of destructor method --> $DIR/explicit-call-to-supertrait-dtor.rs:17:14 | LL | self.drop(); - | ^^^^ explicit destructor calls not allowed + | ^^^^ + | | + | explicit destructor calls not allowed + | help: consider using `drop` function: `drop(self)` error: aborting due to previous error diff --git a/src/test/ui/illegal-ufcs-drop.stderr b/src/test/ui/illegal-ufcs-drop.stderr index d35d376962c17..922d50d259569 100644 --- a/src/test/ui/illegal-ufcs-drop.stderr +++ b/src/test/ui/illegal-ufcs-drop.stderr @@ -2,7 +2,10 @@ error[E0040]: explicit use of destructor method --> $DIR/illegal-ufcs-drop.rs:8:5 | LL | Drop::drop(&mut Foo) - | ^^^^^^^^^^ explicit destructor calls not allowed + | ^^^^^^^^^^ + | | + | explicit destructor calls not allowed + | help: consider using `drop` function error: aborting due to previous error