Skip to content

Fix expect_fun_call producing invalid suggestions #15122

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

sethdusek
Copy link

@sethdusek sethdusek commented Jun 24, 2025

Previously expect_fun_call would too eagerly convert cases like foo.expect(if | block | match) into foo.unwrap_or_else. Additionally, it would also add to_string() even though the argument is being passed into format!() which can accept a &str. I also discovered some other cases where this lint would either produce invalid results, or be triggered unnecessarily:

  • Clippy would suggest changing expect to unwrap_or_else even if the expression inside expect contains a return statement
  • opt.expect(const_fn()) no longer triggers the lint
  • The lint would always add braces to the closure body, even if the body of expect is a single expression
  • opt.expect({"literal"}) used to get turned into opt.unwrap_or_else(|| panic!("{}", {"literal"}.to_string()))

Fixes #15056

changelog: [expect_fun_call]: fix expect_fun_call producing invalid suggestions

@rustbot
Copy link
Collaborator

rustbot commented Jun 24, 2025

r? @samueltardieu

rustbot has assigned @samueltardieu.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Jun 24, 2025
@samueltardieu
Copy link
Contributor

* opt.expect(const_fn()) no longer triggers the lint

What's the rationale behind this? const_fn() is not evaluated at compile time here.

@samueltardieu
Copy link
Contributor

samueltardieu commented Jul 1, 2025

Note: this doesn't fix #15195 (nor does it pretend to)

@sethdusek
Copy link
Author

* opt.expect(const_fn()) no longer triggers the lint

What's the rationale behind this? const_fn() is not evaluated at compile time here.

* opt.expect(const_fn()) no longer triggers the lint

What's the rationale behind this? const_fn() is not evaluated at compile time here.

This behavior is inherited from switch_to_lazy_eval() which is also used by the or_fun_call lint, and opt.unwrap_or(const_fn()) doesn't trigger that lint either. But this is definitely a bug since const_call would still get evaluated at runtime:

#![warn(clippy::or_fun_call)]
fn call() -> i32 {
    0
}
const fn const_call() -> i32 {
    0
}
fn opt() -> Option<i32> {
    None
}
fn main() {
    let a: Option<i32> = opt();
    a.unwrap_or(call()); // triggers the lint
    a.unwrap_or(const_call()); // doesn't trigger
}

Playground link

Should I try to address this in this same PR or handle it separately?

@sethdusek

This comment was marked as outdated.

@samueltardieu
Copy link
Contributor

Note: this doesn't fix #15195 (nor does it pretend to)

This PR turns the snippet into:

error: function call inside of `expect`
 --> /tmp/foo.rs:6:11
  |
6 |     _ = x.expect(std::convert::identity(s));
  |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{}", std::convert::identity(s)))`

which compiles

As far as I can see while testing, it doesn't allow s to be typed anymore, even with this PR.

@samueltardieu
Copy link
Contributor

Should I try to address this in this same PR or handle it separately?

A separate PR (prerequisite for this one) would be preferable as to evaluate the effects on other callers of the eagerness evaluator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Garbage clippy::expect_fun_call lint for result.expect(if b { "" } else { "" })
3 participants