diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 0491cde4f..b7646dd6f 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 1f2f46b03..b35071546 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 { - let fx = box A; - fx // moved out, "escapes" + box A // moved out, "escapes" } fn nowarn_move() { @@ -139,3 +136,28 @@ pub struct PeekableSeekable { pub fn new(_needs_name: Box>) -> () { } + +/// 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); +} + +impl BoxedAction for u64 { + fn do_sth(self: Box) { + 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 MyTrait for Box { + fn do_sth(self) {} +} diff --git a/tests/ui/escape_analysis.stderr b/tests/ui/escape_analysis.stderr index e69de29bb..25ba413b7 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) { + | ^ + | + = 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>) -> () { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors +