|
1 | 1 | # G.FUD.04 Should input by-value but by-ref if parameter derived `Copy`, and its value is a small enough number
|
| 2 | + |
| 3 | +**[Level] Advice** |
| 4 | + |
| 5 | +**[Description]** |
| 6 | + |
| 7 | +Generally, it is avoided to input by-ref when parameter's value is a small enough number and derived `Copy`. That's because as for such small values, from the perspective of performance, by-value is as fast as by-ref, and it could also make code more readable. It is also recommended to input by-value for some tiny `struct`, but should notice **[Exception]** cases. |
| 8 | + |
| 9 | +**[Bad Case]** |
| 10 | + |
| 11 | +```rust |
| 12 | +#![warn(clippy::trivially_copy_pass_by_ref)] |
| 13 | + |
| 14 | +// Not Good |
| 15 | +fn foo(v: &u32) { ... } |
| 16 | +``` |
| 17 | + |
| 18 | +**[Good Case]** |
| 19 | + |
| 20 | +```rust |
| 21 | +#![warn(clippy::trivially_copy_pass_by_ref)] |
| 22 | + |
| 23 | +// Good |
| 24 | +fn foo(v: u32) { ... } |
| 25 | +``` |
| 26 | + |
| 27 | +**[Exception]** |
| 28 | + |
| 29 | +Should notice following cases, lint checker would report trivial warnings because of its conservativeness. |
| 30 | + |
| 31 | +```rust |
| 32 | +#[derive(Clone, Copy)] |
| 33 | +struct RawPoint { |
| 34 | + pub x: u8, |
| 35 | +} |
| 36 | + |
| 37 | +#[derive(Clone, Copy)] |
| 38 | +struct Point { |
| 39 | + pub raw: RawPoint, |
| 40 | +} |
| 41 | + |
| 42 | +impl Point { |
| 43 | + pub fn raw(&self) -> *const RawPoint { |
| 44 | + &self.raw |
| 45 | + } |
| 46 | + |
| 47 | + // if you conform lint checker, change above `raw(&self)`'s parameter `&self` into `self`(delete ref), it is `raw_linted(self)`. That also works well in unoptimized cases(just like `cargo build`, the debug mode), but doesn't work in optimized cases(i.e. `cargo build --release`, the release mode) because of following reasons. |
| 48 | + pub fn raw_linted(self) -> *const RawPoint { |
| 49 | + &self.raw |
| 50 | + } |
| 51 | +} |
| 52 | + |
| 53 | +fn main() { |
| 54 | + let p = Point { raw: RawPoint { x: 10 } }; |
| 55 | + |
| 56 | + // This passes |
| 57 | + assert_eq!(p.raw(), p.raw()); |
| 58 | + |
| 59 | + // This fails |
| 60 | + // Actually, in optimized cases, the activity of function has been changed if not using `self` as shared ref. |
| 61 | + // Because struct Point derived Copy trait, everytime we call raw_linted() method, its instance would be copied, and return a different pointer. |
| 62 | + assert_eq!(p.raw_linted(), p.raw_linted()); |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +**[Lint Check]** |
| 67 | + |
| 68 | +| lint name | Clippy check | Rustc check | Lint Group | Level | |
| 69 | +| --------- | ------------ | ----------- | ---------- | ----- | |
| 70 | +| [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/#trivially_copy_pass_by_ref) | yes | no | pedanic | allow | |
| 71 | + |
| 72 | +This lint corresponds to the following configuration of `clippy.toml` |
| 73 | + |
| 74 | +```toml |
| 75 | +# if it is an exported API, the lint checker would not be triggered, which avoid unexpected modifications. |
| 76 | +avoid-breaking-exported-api=true |
| 77 | + |
| 78 | +# consider the maximum size (bytes) of by-value pass with Copy. The default is None. |
| 79 | +trivial-copy-size-limit=None |
| 80 | +``` |
| 81 | +**Tips:** this lint would not consider the cases using pointer, just like example in **[Exception]** part. |
| 82 | + |
| 83 | +Reference of **[Exception]** example: [rust-clippy/issues/5953](https://github.com/rust-lang/rust-clippy/issues/5953). |
0 commit comments