Rust-clippy: or_fun_call triggers on const fn

Created on 28 May 2020  路  11Comments  路  Source: rust-lang/rust-clippy

const fn f(v: i32) -> Option<i32> {
    Some(v)
}

fn main() {
    None.or(f(1));  // try this: `or_else(|| f(1))`
}
E-medium L-enhancement

All 11 comments

cc #1609

Linking this relevant comment so that it does not get buried in a closed PR: https://github.com/rust-lang/rust-clippy/pull/5682#issuecomment-638681210

Are const fn calls with const arguments guaranteed to be evaluated at compile-time?

From the unstable book I understand that they can be called in a const context, but nothing about evaluation guarantees.

Are const fn calls with const arguments guaranteed to be evaluated at compile-time?

Good question. @oli-obk can you give some insights here?

@montrivo No, it is only guaranteed to evaluate at compile time in const item or static item.

@montrivo No, it is only guaranteed to evaluate at compile time in const item or static item.

If so, then I don't think clippy should handle const fns the way proposed in this issue's description, unless the const fn call is used in an expression assigned to a const variable.

Continuing on @oli-obk 's example:

const fn compute_nth_prime(n: usize) -> Option<usize> {
    // super heavy logic here
}

// here recommending `unwrap_or_else` is questionable since there is no runtime performance improvement 
// (although it might improve compilation time if `compute_nth_prime` is really heavy)
const a_prime_number: i32 = Some(13).unwrap_or(comput_nth_prime(42));

// here the lint is applicable, as unwrap_or will cause an unnecessary runtime cost 
// given compute_nth_prime(42) is not evaluated during compilation
fn main() {
  println!("{}", Some(42).unwrap_or(compute_nth_prime(42)));
}

Are const fn calls with const arguments guaranteed to be evaluated at compile-time?

That's a good question, indeed, but I would say Clippy should be interested in if it could be evaluated at compile time.

If it can (even though not guaranteed), suggesting the or_else variants can be considered a false positive. In cases it's not evaluated at compile time, it's just a false negative.

(I was mistaken)

Relevant Zulip conversation, IIUC @montrivo is on the right track. On my side, I was confused between constant evaluation and constant propagation, the latter has nothing to do with const fn.

@ebroto I think nullary const fn should not be treated specifically in or_fun_call. We should revert #5889 and #5984.

@montrivo I think you're right, I've opened #6077 to revert them.

Continuing with your example, IIUC none of the methods linted by or_fun_call can be called in a const or static initializer because they are not const fns (so the first case will not compile) and the lint should treat const fns like any other function, because it will never lint in const contexts (well, at least until a potential definition of those methods as const fn).

@mahkoh I'm going to close this issue as I think this is not a false positive, feel free to reopen in case you think otherwise.

Was this page helpful?
0 / 5 - 0 ratings