diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 6a048b19213..a01a1c5ae31 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -124,10 +124,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { // Use lifetimes to determine if we're returning a reference to the // argument. In that case we can't switch to pass-by-value as the // argument will not live long enough. - let output_lt = if let TypeVariants::TyRef(output_lt, _, _) = fn_sig.output().sty { - Some(output_lt) - } else { - None + let output_lts = match fn_sig.output().sty { + TypeVariants::TyRef(output_lt, _, _) => vec![output_lt], + TypeVariants::TyAdt(_, substs) => substs.regions().collect(), + _ => vec![], }; for ((input, &ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) { @@ -138,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { if_chain! { if let TypeVariants::TyRef(input_lt, ty, Mutability::MutImmutable) = ty.sty; - if Some(input_lt) != output_lt; + if !output_lts.contains(&input_lt); if is_copy(cx, ty); if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); if size <= self.limit; diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index c6773add244..9b905e8d628 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -6,6 +6,10 @@ struct Foo(u32); #[derive(Copy, Clone)] struct Bar([u8; 24]); +struct FooRef<'a> { + foo: &'a Foo, +} + type Baz = u32; fn good(a: &mut u32, b: u32, c: &Bar) { @@ -20,6 +24,19 @@ fn good_return_explicit_lt_ref<'a>(foo: &'a Foo) -> &'a u32 { &foo.0 } +fn good_return_implicit_lt_struct(foo: &Foo) -> FooRef { + FooRef { + foo, + } +} + +#[allow(needless_lifetimes)] +fn good_return_explicit_lt_struct<'a>(foo: &'a Foo) -> FooRef<'a> { + FooRef { + foo, + } +} + fn bad(x: &u32, y: &Foo, z: &Baz) { } diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index db25cc5a020..757b6b4c9a9 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,81 +1,81 @@ error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:23:11 + --> $DIR/trivially_copy_pass_by_ref.rs:40:11 | -23 | fn bad(x: &u32, y: &Foo, z: &Baz) { +40 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` | = note: `-D trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:23:20 + --> $DIR/trivially_copy_pass_by_ref.rs:40:20 | -23 | fn bad(x: &u32, y: &Foo, z: &Baz) { +40 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:23:29 + --> $DIR/trivially_copy_pass_by_ref.rs:40:29 | -23 | fn bad(x: &u32, y: &Foo, z: &Baz) { +40 | fn bad(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:33:12 + --> $DIR/trivially_copy_pass_by_ref.rs:50:12 | -33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^^ help: consider passing by value instead: `self` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:33:22 + --> $DIR/trivially_copy_pass_by_ref.rs:50:22 | -33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:33:31 + --> $DIR/trivially_copy_pass_by_ref.rs:50:31 | -33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:33:40 + --> $DIR/trivially_copy_pass_by_ref.rs:50:40 | -33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { +50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:36:16 + --> $DIR/trivially_copy_pass_by_ref.rs:53:16 | -36 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +53 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:36:25 + --> $DIR/trivially_copy_pass_by_ref.rs:53:25 | -36 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +53 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:36:34 + --> $DIR/trivially_copy_pass_by_ref.rs:53:34 | -36 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +53 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:50:16 + --> $DIR/trivially_copy_pass_by_ref.rs:67:16 | -50 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +67 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `u32` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:50:25 + --> $DIR/trivially_copy_pass_by_ref.rs:67:25 | -50 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +67 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Foo` error: this argument is passed by reference, but would be more efficient if passed by value - --> $DIR/trivially_copy_pass_by_ref.rs:50:34 + --> $DIR/trivially_copy_pass_by_ref.rs:67:34 | -50 | fn bad2(x: &u32, y: &Foo, z: &Baz) { +67 | fn bad2(x: &u32, y: &Foo, z: &Baz) { | ^^^^ help: consider passing by value instead: `Baz` error: aborting due to 13 previous errors