Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

False positive for or_fun_call #1609

Closed
tbu- opened this issue Mar 7, 2017 · 6 comments
Closed

False positive for or_fun_call #1609

tbu- opened this issue Mar 7, 2017 · 6 comments
Labels
C-bug Category: Clippy is not doing the correct thing E-medium Call for participation: Medium difficulty level problem and requires some initial experience. I-false-positive Issue: The lint was triggered on code it shouldn't have T-middle Type: Probably requires verifiying types

Comments

@tbu-
Copy link

tbu- commented Mar 7, 2017

I got the following message:

warning: use of `ok_or` followed by a function call
   --> src/file.rs:220:5
    |
220 |     o.ok_or(io::Error::new(io::ErrorKind::InvalidData, SeekOverflow(())))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: #[warn(or_fun_call)] on by default
help: try this
    |     o.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, SeekOverflow(())))
    = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#or_fun_call

AIUI, this does not invoke allocations (SeekOverflow is a zero-sized struct (ZST) and ZSTs aren't actually allocated), and can be const-folded by the compiler. Thus, this ok_or_else shouldn't provide benefit over ok_or.

To make it a bit more obvious, here's an example that definitely doesn't invoke any allocations:

warning: use of `ok_or` followed by a function call
 --> src/lib.rs:4:38
  |
4 |     let x: Result<(), AtomicUsize> = Some(()).ok_or(AtomicUsize::new(0));
  |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(or_fun_call)] on by default
help: try this
  |     let x: Result<(), AtomicUsize> = Some(()).ok_or_else(|| AtomicUsize::new(0));
  = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#or_fun_call
@oli-obk
Copy link
Contributor

oli-obk commented Mar 7, 2017

I thought we fixed this...

@oli-obk oli-obk added E-medium Call for participation: Medium difficulty level problem and requires some initial experience. C-bug Category: Clippy is not doing the correct thing T-middle Type: Probably requires verifiying types labels Mar 7, 2017
@Vlad-Shcherbina
Copy link
Contributor

The problem is still there.

struct Zst {}

fn z(_: i32) -> Zst { Zst {} }

fn f(_: i32) -> i32 { 42 }

fn main() {
    let _ = Some(Zst {}).unwrap_or(z(1));
    let _ = Some(42).unwrap_or(f(1));
}

Both produce Clippy warnings:

warning: use of `unwrap_or` followed by a function call
 --> src\main.rs:8:26
  |
8 |     let _ = Some(Zst {}).unwrap_or(z(1));
  |                          ^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| z(1))`
  |
  = note: #[warn(clippy::or_fun_call)] on by default
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call

warning: use of `unwrap_or` followed by a function call
 --> src\main.rs:9:22
  |
9 |     let _ = Some(42).unwrap_or(f(1));
  |                      ^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| f(1))`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call

I think this warning should be suppressed (or moved to pedantic) for types that impl Copy.


Version info:

> cargo --version --verbose
cargo 1.37.0-nightly (545f35425 2019-05-23)
release: 1.37.0
commit-hash: 545f354259be4e9745ea00a524c0e4c51df01aa6
commit-date: 2019-05-23

> cargo clippy --version
clippy 0.0.212 (20da8f45 2019-06-03)

@upsuper
Copy link
Contributor

upsuper commented Dec 8, 2019

The return type is Copy doesn't mean the function call itself is trivial. For example you can totally do

fn request_default_value() -> i32 {
    // do some network request to get the value
}
let _ = option.unwrap_or(request_default_value());

and in this case Clippy should definitely issue this warning.

But I think this situation is indeed improvable. I suggest that Clippy should not issue this warning if it's a const expression, i.e. its value can be computed at compile time.

AtomicUsize::new is already a const fn, thus this issue would be resolved. In @Vlad-Shcherbina's comment, apparently the two functions can be marked const as well (when const fn is stabilized).

@phansch phansch added the I-false-positive Issue: The lint was triggered on code it shouldn't have label Dec 18, 2020
@Ekleog
Copy link

Ekleog commented Dec 21, 2020

Seeing the reasoning for closing #5658 ; should this not be closed too?

(Disclaimer: I came here wanting to report this exact same issue, and I do believe that my .or_else(Duration::from_secs(0)) would be clearer than adding the const clippy just made me add for most likely no performance loss, but anyway)

@Allen-Webb
Copy link

I hit this with clippy 0.0.212:
.unwrap_or(Duration::from_secs(0))

warning: use of `unwrap_or` followed by a function call
   --> src/linux.rs:105:14
    |
105 |             .unwrap_or(Duration::from_secs(0));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Duration::from_secs(0))`
    |
    = note: `#[warn(clippy::or_fun_call)]` on by default
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call

warning: 1 warning emitted

If this wasn't a constant function, it wouldn't be allowed for initialization of statics (e.g. static TIMEOUT: Duration = Duration::from_secs(15);). In my opinion any function that is allowed for the initialization of a static variable shouldn't trigger this warning.

@camsteffen
Copy link
Contributor

Seeing the reasoning for closing #5658 ; should this not be closed too?

@Ekleog I agree. Closing.

For the original example, Clippy has no way of knowing how expensive io::Error::new will be.

In my opinion any function that is allowed for the initialization of a static variable shouldn't trigger this warning.

@Allen-Webb Building off the discussion in #5658, you could have static TIMEOUT: Duration = Duration::from_secs(compute_nth_prime(42)).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: Clippy is not doing the correct thing E-medium Call for participation: Medium difficulty level problem and requires some initial experience. I-false-positive Issue: The lint was triggered on code it shouldn't have T-middle Type: Probably requires verifiying types
Projects
None yet
Development

No branches or pull requests

8 participants