expect_fun_call: only lint const fn's if they're not inside a const context

This commit is contained in:
Kamal Ahmad 2025-07-14 18:29:30 +05:00
parent 07e2d96eff
commit fcd064da75
4 changed files with 43 additions and 9 deletions

View file

@ -1,15 +1,16 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::eager_or_lazy::switch_to_lazy_eval;
use clippy_utils::macros::{FormatArgsStorage, format_args_inputs_span, root_macro_call_first_node};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::{contains_return, peel_blocks};
use clippy_utils::visitors::for_each_expr;
use clippy_utils::{contains_return, is_inside_always_const_context, peel_blocks};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
use std::borrow::Cow;
use std::ops::ControlFlow;
use super::EXPECT_FUN_CALL;
@ -48,10 +49,23 @@ pub(super) fn check<'tcx>(
arg_root
}
fn contains_call<'a>(cx: &LateContext<'a>, arg: &'a hir::Expr<'a>) -> bool {
for_each_expr(cx, arg, |expr| {
if matches!(expr.kind, hir::ExprKind::MethodCall { .. } | hir::ExprKind::Call { .. })
&& !is_inside_always_const_context(cx.tcx, expr.hir_id)
{
ControlFlow::Break(())
} else {
ControlFlow::Continue(())
}
})
.is_some()
}
if name == sym::expect
&& let [arg] = args
&& let arg_root = get_arg_root(cx, arg)
&& switch_to_lazy_eval(cx, arg_root)
&& contains_call(cx, arg_root)
&& !contains_return(arg_root)
{
let receiver_type = cx.typeck_results().expr_ty_adjusted(receiver);

View file

@ -106,7 +106,14 @@ fn main() {
Some("foo").unwrap_or_else(|| panic!("{}", get_non_static_str(&0)));
//~^ expect_fun_call
Some("foo").expect(const_evaluable());
Some("foo").unwrap_or_else(|| panic!("{}", const_evaluable()));
//~^ expect_fun_call
const {
Some("foo").expect(const_evaluable());
}
Some("foo").expect(const { const_evaluable() });
}
//Issue #3839

View file

@ -107,6 +107,13 @@ fn main() {
//~^ expect_fun_call
Some("foo").expect(const_evaluable());
//~^ expect_fun_call
const {
Some("foo").expect(const_evaluable());
}
Some("foo").expect(const { const_evaluable() });
}
//Issue #3839

View file

@ -68,28 +68,34 @@ LL | Some("foo").expect(get_non_static_str(&0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{}", get_non_static_str(&0)))`
error: function call inside of `expect`
--> tests/ui/expect_fun_call.rs:113:16
--> tests/ui/expect_fun_call.rs:109:21
|
LL | Some("foo").expect(const_evaluable());
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{}", const_evaluable()))`
error: function call inside of `expect`
--> tests/ui/expect_fun_call.rs:120:16
|
LL | Some(true).expect(&format!("key {}, {}", 1, 2));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))`
error: function call inside of `expect`
--> tests/ui/expect_fun_call.rs:120:17
--> tests/ui/expect_fun_call.rs:127:17
|
LL | opt_ref.expect(&format!("{:?}", opt_ref));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{:?}", opt_ref))`
error: function call inside of `expect`
--> tests/ui/expect_fun_call.rs:125:20
--> tests/ui/expect_fun_call.rs:132:20
|
LL | format_capture.expect(&format!("{error_code}"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}"))`
error: function call inside of `expect`
--> tests/ui/expect_fun_call.rs:129:30
--> tests/ui/expect_fun_call.rs:136:30
|
LL | format_capture_and_value.expect(&format!("{error_code}, {}", 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}, {}", 1))`
error: aborting due to 15 previous errors
error: aborting due to 16 previous errors