G.FUD.04 Should input by-value but by-ref if parameter derived Copy, and its value is a small enough number

[Level] Advice

[Description]

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.

[Bad Case]


#![allow(unused)]
#![warn(clippy::trivially_copy_pass_by_ref)]

fn main() {
// Not Good
fn foo(v: &u32) { ... }
}

[Good Case]


#![allow(unused)]
#![warn(clippy::trivially_copy_pass_by_ref)]

fn main() {
// Good
fn foo(v: u32) { ... }
}

[Exception]

Should notice following cases, lint checker would report trivial warnings because of its conservativeness.

#[derive(Clone, Copy)]
struct RawPoint {
    pub x: u8,
}

#[derive(Clone, Copy)]
struct Point {
    pub raw: RawPoint,
}

impl Point {
    pub fn raw(&self) -> *const RawPoint {
        &self.raw
    }

    // 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.
    pub fn raw_linted(self) -> *const RawPoint {
        &self.raw
    }
}

fn main() {
    let p = Point { raw: RawPoint { x: 10 } };

    // This passes
    assert_eq!(p.raw(), p.raw());

    // This fails
    // Actually, in optimized cases, the activity of function has been changed if not using `self` as shared ref.
    // Because struct Point derived Copy trait, everytime we call raw_linted() method, its instance would be copied, and return a different pointer.
    assert_eq!(p.raw_linted(), p.raw_linted());
}

[Lint Check]

lint nameClippy checkRustc checkLint GroupLevel
trivially_copy_pass_by_refyesnopedanicallow

This lint corresponds to the following configuration of clippy.toml

# if it is an exported API, the lint checker would not be triggered, which avoid unexpected modifications.
avoid-breaking-exported-api=true

# consider the maximum size (bytes) of by-value pass with Copy. The default is None.
trivial-copy-size-limit=None

Tips: this lint would not consider the cases using pointer, just like example in [Exception] part.

Reference of [Exception] example: rust-clippy/issues/5953.