about summary refs log tree commit diff
diff options
context:
space:
mode:
authorStanislav Tkach <stanislav.tkach@gmail.com>2020-05-20 17:48:21 +0300
committerStanislav Tkach <stanislav.tkach@gmail.com>2020-05-21 16:21:02 +0300
commit34b51187ce8fa261ebe3bef4a9a26135b919ac02 (patch)
tree4f22edf477054b18aa1c999694b474a2d669f145
parent672b272077561ca7b5027a8aff9ea2957c7d4c21 (diff)
downloadrust-34b51187ce8fa261ebe3bef4a9a26135b919ac02.tar.gz
rust-34b51187ce8fa261ebe3bef4a9a26135b919ac02.zip
Suggest using std::mem::drop function instead of explicit destructor call
-rw-r--r--src/librustc_typeck/check/callee.rs26
-rw-r--r--src/librustc_typeck/check/method/confirm.rs9
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/test/ui/error-codes/E0040.stderr5
-rw-r--r--src/test/ui/explicit/explicit-call-to-dtor.stderr5
-rw-r--r--src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr5
-rw-r--r--src/test/ui/illegal-ufcs-drop.stderr5
7 files changed, 45 insertions, 12 deletions
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 52ddacc1c4b..4c31363f2c0 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<Span>,
+    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 c4805c54a7d..38a5bd5fce0 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 d72c74e4188..3ac3934bea3 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 96645590281..69cf28b2970 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 cbbe967179e..5ebe4ee4b90 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 0b302e30b64..cd3fb3119a5 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 d35d376962c..922d50d2595 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