about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBruno Kirschner <bruno.kirschner@online.de>2018-10-15 20:20:50 +0200
committerBruno Kirschner <bruno.kirschner@online.de>2018-10-15 20:34:45 +0200
commit2d8b4f3d5cb771a67f119f3903dd4aca1e4c9136 (patch)
tree2a15a96dc9eebbfab277bd077ee7ee11f8216c17
parent0f4b13bc1bbd43ed21878c21291dddde7e4b9028 (diff)
downloadrust-2d8b4f3d5cb771a67f119f3903dd4aca1e4c9136.tar.gz
rust-2d8b4f3d5cb771a67f119f3903dd4aca1e4c9136.zip
Avoid linting `boxed_local` on trait implementations.
-rw-r--r--clippy_lints/src/escape.rs13
-rw-r--r--tests/ui/escape_analysis.rs34
-rw-r--r--tests/ui/escape_analysis.stderr16
3 files changed, 56 insertions, 7 deletions
diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs
index 0491cde4fed..b7646dd6fdf 100644
--- a/clippy_lints/src/escape.rs
+++ b/clippy_lints/src/escape.rs
@@ -65,6 +65,7 @@ impl LintPass for Pass {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
+
     fn check_fn(
         &mut self,
         cx: &LateContext<'a, 'tcx>,
@@ -74,13 +75,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
         _: Span,
         node_id: NodeId,
     ) {
-        let fn_def_id = cx.tcx.hir.local_def_id(node_id);
+        // If the method is an impl for a trait, don't warn
+        let parent_id = cx.tcx.hir.get_parent(node_id);
+        let parent_node = cx.tcx.hir.find(parent_id);
+
+        if let Some(Node::Item(item)) = parent_node {
+            if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node {
+                return;
+            }
+        }
+
         let mut v = EscapeDelegate {
             cx,
             set: NodeSet(),
             too_large_for_stack: self.too_large_for_stack,
         };
 
+        let fn_def_id = cx.tcx.hir.local_def_id(node_id);
         let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id);
         ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).consume_body(body);
 
diff --git a/tests/ui/escape_analysis.rs b/tests/ui/escape_analysis.rs
index 1f2f46b03cd..b35071546e7 100644
--- a/tests/ui/escape_analysis.rs
+++ b/tests/ui/escape_analysis.rs
@@ -7,12 +7,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 #![feature(box_syntax)]
 
-#![allow(warnings, clippy)]
-
-#![warn(boxed_local)]
+#![allow(clippy::borrowed_box, clippy::needless_pass_by_value, clippy::unused_unit)]
+#![warn(clippy::boxed_local)]
 
 #[derive(Clone)]
 struct A;
@@ -70,8 +68,7 @@ fn warn_pass() {
 }
 
 fn nowarn_return() -> Box<A> {
-    let fx = box A;
-    fx // moved out, "escapes"
+    box A // moved out, "escapes"
 }
 
 fn nowarn_move() {
@@ -139,3 +136,28 @@ pub struct PeekableSeekable<I: Foo> {
 
 pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {
 }
+
+/// Regression for #916, #1123
+///
+/// This shouldn't warn for `boxed_local`as the implementation of a trait
+/// can't change much about the trait definition.
+trait BoxedAction {
+    fn do_sth(self: Box<Self>);
+}
+
+impl BoxedAction for u64 {
+    fn do_sth(self: Box<Self>) {
+        println!("{}", *self)
+    }
+}
+
+/// Regression for #1478
+///
+/// This shouldn't warn for `boxed_local`as self itself is a box type.
+trait MyTrait {
+    fn do_sth(self);
+}
+
+impl<T> MyTrait for Box<T> {
+    fn do_sth(self) {}
+}
diff --git a/tests/ui/escape_analysis.stderr b/tests/ui/escape_analysis.stderr
index e69de29bb2d..25ba413b75a 100644
--- a/tests/ui/escape_analysis.stderr
+++ b/tests/ui/escape_analysis.stderr
@@ -0,0 +1,16 @@
+error: local variable doesn't need to be boxed here
+  --> $DIR/escape_analysis.rs:45:13
+   |
+45 | fn warn_arg(x: Box<A>) {
+   |             ^
+   |
+   = note: `-D clippy::boxed-local` implied by `-D warnings`
+
+error: local variable doesn't need to be boxed here
+   --> $DIR/escape_analysis.rs:137:12
+    |
+137 | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {
+    |            ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+