Skip to content

Commit 5d9ca00

Browse files
authored
Merge pull request #2992 from etaoins/allow-pass-by-ref-on-adt-return
Allow pass by ref when returning ADT with ref
2 parents 40349b2 + 08d6b3d commit 5d9ca00

File tree

3 files changed

+48
-31
lines changed

3 files changed

+48
-31
lines changed

clippy_lints/src/trivially_copy_pass_by_ref.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
124124
// Use lifetimes to determine if we're returning a reference to the
125125
// argument. In that case we can't switch to pass-by-value as the
126126
// argument will not live long enough.
127-
let output_lt = if let TypeVariants::TyRef(output_lt, _, _) = fn_sig.output().sty {
128-
Some(output_lt)
129-
} else {
130-
None
127+
let output_lts = match fn_sig.output().sty {
128+
TypeVariants::TyRef(output_lt, _, _) => vec![output_lt],
129+
TypeVariants::TyAdt(_, substs) => substs.regions().collect(),
130+
_ => vec![],
131131
};
132132

133133
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 {
138138

139139
if_chain! {
140140
if let TypeVariants::TyRef(input_lt, ty, Mutability::MutImmutable) = ty.sty;
141-
if Some(input_lt) != output_lt;
141+
if !output_lts.contains(&input_lt);
142142
if is_copy(cx, ty);
143143
if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes());
144144
if size <= self.limit;

tests/ui/trivially_copy_pass_by_ref.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ struct Foo(u32);
66
#[derive(Copy, Clone)]
77
struct Bar([u8; 24]);
88

9+
struct FooRef<'a> {
10+
foo: &'a Foo,
11+
}
12+
913
type Baz = u32;
1014

1115
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 {
2024
&foo.0
2125
}
2226

27+
fn good_return_implicit_lt_struct(foo: &Foo) -> FooRef {
28+
FooRef {
29+
foo,
30+
}
31+
}
32+
33+
#[allow(needless_lifetimes)]
34+
fn good_return_explicit_lt_struct<'a>(foo: &'a Foo) -> FooRef<'a> {
35+
FooRef {
36+
foo,
37+
}
38+
}
39+
2340
fn bad(x: &u32, y: &Foo, z: &Baz) {
2441
}
2542

tests/ui/trivially_copy_pass_by_ref.stderr

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,81 @@
11
error: this argument is passed by reference, but would be more efficient if passed by value
2-
--> $DIR/trivially_copy_pass_by_ref.rs:23:11
2+
--> $DIR/trivially_copy_pass_by_ref.rs:40:11
33
|
4-
23 | fn bad(x: &u32, y: &Foo, z: &Baz) {
4+
40 | fn bad(x: &u32, y: &Foo, z: &Baz) {
55
| ^^^^ help: consider passing by value instead: `u32`
66
|
77
= note: `-D trivially-copy-pass-by-ref` implied by `-D warnings`
88

99
error: this argument is passed by reference, but would be more efficient if passed by value
10-
--> $DIR/trivially_copy_pass_by_ref.rs:23:20
10+
--> $DIR/trivially_copy_pass_by_ref.rs:40:20
1111
|
12-
23 | fn bad(x: &u32, y: &Foo, z: &Baz) {
12+
40 | fn bad(x: &u32, y: &Foo, z: &Baz) {
1313
| ^^^^ help: consider passing by value instead: `Foo`
1414

1515
error: this argument is passed by reference, but would be more efficient if passed by value
16-
--> $DIR/trivially_copy_pass_by_ref.rs:23:29
16+
--> $DIR/trivially_copy_pass_by_ref.rs:40:29
1717
|
18-
23 | fn bad(x: &u32, y: &Foo, z: &Baz) {
18+
40 | fn bad(x: &u32, y: &Foo, z: &Baz) {
1919
| ^^^^ help: consider passing by value instead: `Baz`
2020

2121
error: this argument is passed by reference, but would be more efficient if passed by value
22-
--> $DIR/trivially_copy_pass_by_ref.rs:33:12
22+
--> $DIR/trivially_copy_pass_by_ref.rs:50:12
2323
|
24-
33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {
24+
50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {
2525
| ^^^^^ help: consider passing by value instead: `self`
2626

2727
error: this argument is passed by reference, but would be more efficient if passed by value
28-
--> $DIR/trivially_copy_pass_by_ref.rs:33:22
28+
--> $DIR/trivially_copy_pass_by_ref.rs:50:22
2929
|
30-
33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {
30+
50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {
3131
| ^^^^ help: consider passing by value instead: `u32`
3232

3333
error: this argument is passed by reference, but would be more efficient if passed by value
34-
--> $DIR/trivially_copy_pass_by_ref.rs:33:31
34+
--> $DIR/trivially_copy_pass_by_ref.rs:50:31
3535
|
36-
33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {
36+
50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {
3737
| ^^^^ help: consider passing by value instead: `Foo`
3838

3939
error: this argument is passed by reference, but would be more efficient if passed by value
40-
--> $DIR/trivially_copy_pass_by_ref.rs:33:40
40+
--> $DIR/trivially_copy_pass_by_ref.rs:50:40
4141
|
42-
33 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {
42+
50 | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {
4343
| ^^^^ help: consider passing by value instead: `Baz`
4444

4545
error: this argument is passed by reference, but would be more efficient if passed by value
46-
--> $DIR/trivially_copy_pass_by_ref.rs:36:16
46+
--> $DIR/trivially_copy_pass_by_ref.rs:53:16
4747
|
48-
36 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
48+
53 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
4949
| ^^^^ help: consider passing by value instead: `u32`
5050

5151
error: this argument is passed by reference, but would be more efficient if passed by value
52-
--> $DIR/trivially_copy_pass_by_ref.rs:36:25
52+
--> $DIR/trivially_copy_pass_by_ref.rs:53:25
5353
|
54-
36 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
54+
53 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
5555
| ^^^^ help: consider passing by value instead: `Foo`
5656

5757
error: this argument is passed by reference, but would be more efficient if passed by value
58-
--> $DIR/trivially_copy_pass_by_ref.rs:36:34
58+
--> $DIR/trivially_copy_pass_by_ref.rs:53:34
5959
|
60-
36 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
60+
53 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
6161
| ^^^^ help: consider passing by value instead: `Baz`
6262

6363
error: this argument is passed by reference, but would be more efficient if passed by value
64-
--> $DIR/trivially_copy_pass_by_ref.rs:50:16
64+
--> $DIR/trivially_copy_pass_by_ref.rs:67:16
6565
|
66-
50 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
66+
67 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
6767
| ^^^^ help: consider passing by value instead: `u32`
6868

6969
error: this argument is passed by reference, but would be more efficient if passed by value
70-
--> $DIR/trivially_copy_pass_by_ref.rs:50:25
70+
--> $DIR/trivially_copy_pass_by_ref.rs:67:25
7171
|
72-
50 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
72+
67 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
7373
| ^^^^ help: consider passing by value instead: `Foo`
7474

7575
error: this argument is passed by reference, but would be more efficient if passed by value
76-
--> $DIR/trivially_copy_pass_by_ref.rs:50:34
76+
--> $DIR/trivially_copy_pass_by_ref.rs:67:34
7777
|
78-
50 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
78+
67 | fn bad2(x: &u32, y: &Foo, z: &Baz) {
7979
| ^^^^ help: consider passing by value instead: `Baz`
8080

8181
error: aborting due to 13 previous errors

0 commit comments

Comments
 (0)