diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 52ddacc1c4b1a..f4e46a0493151 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -21,11 +21,31 @@ 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 = + if snippet.is_empty() { "drop".to_string() } else { format!("drop({})", snippet) }; + + err.span_suggestion( + span, + &format!("consider using `drop` function: `{}`", suggestion), + String::new(), + Applicability::Unspecified, + ); + + err.emit(); } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 410c5efdf37d4..7e4e1aa608ece 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 da711b9d48042..3cb6ce61ee8d7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5433,7 +5433,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..57c99739afd24 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: `drop` error: aborting due to previous error