From 3a712238127424ca7e40f900bc40252f46627c2f Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Thu, 4 Jul 2024 15:56:11 +0800 Subject: [PATCH] [`missing_const_for_fn`]: fix suggestions for fn with abi that requires `const_extern_fn` feature --- clippy_config/src/msrvs.rs | 2 +- clippy_lints/src/missing_const_for_fn.rs | 16 ++++- .../ui/missing_const_for_fn/cant_be_const.rs | 9 +++ .../missing_const_for_fn/could_be_const.fixed | 15 +++++ .../ui/missing_const_for_fn/could_be_const.rs | 15 +++++ .../could_be_const.stderr | 30 ++++++++-- .../could_be_const_with_const_extern_fn.fixed | 14 +++++ .../could_be_const_with_const_extern_fn.rs | 14 +++++ ...could_be_const_with_const_extern_fn.stderr | 59 +++++++++++++++++++ 9 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed create mode 100644 tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs create mode 100644 tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs index a5761d3270c..78fd6149dc0 100644 --- a/clippy_config/src/msrvs.rs +++ b/clippy_config/src/msrvs.rs @@ -25,7 +25,7 @@ msrv_aliases! { 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } 1,63,0 { CLONE_INTO } - 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } + 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_FN } 1,59,0 { THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST } 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF } 1,56,0 { CONST_FN_UNION } diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index bb0d714a31f..44ec1bd08cf 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -11,6 +11,7 @@ use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::Span; +use rustc_target::spec::abi::Abi; declare_clippy_lint! { /// ### What it does @@ -115,7 +116,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { .iter() .any(|param| matches!(param.kind, GenericParamKind::Const { .. })); - if already_const(header) || has_const_generic_params { + if already_const(header) + || has_const_generic_params + || !could_be_const_with_abi(cx, &self.msrv, header.abi) + { return; } }, @@ -171,3 +175,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { fn already_const(header: hir::FnHeader) -> bool { header.constness == Constness::Const } + +fn could_be_const_with_abi(cx: &LateContext<'_>, msrv: &Msrv, abi: Abi) -> bool { + match abi { + Abi::Rust => true, + // `const extern "C"` was stablized after 1.62.0 + Abi::C { unwind: false } => msrv.meets(msrvs::CONST_EXTERN_FN), + // Rest ABIs are still unstable and need the `const_extern_fn` feature enabled. + _ => cx.tcx.features().const_extern_fn, + } +} diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index 2750e0cdf3f..952ff828363 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -180,4 +180,13 @@ mod msrv { unsafe { *self.1 as usize } } } + + #[clippy::msrv = "1.61"] + extern "C" fn c() {} +} + +mod with_extern { + extern "C-unwind" fn c_unwind() {} + extern "system" fn system() {} + extern "system-unwind" fn system_unwind() {} } diff --git a/tests/ui/missing_const_for_fn/could_be_const.fixed b/tests/ui/missing_const_for_fn/could_be_const.fixed index 921dcf0b162..572ca52439a 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.fixed +++ b/tests/ui/missing_const_for_fn/could_be_const.fixed @@ -140,6 +140,21 @@ mod msrv { let bar = Bar { val: 1 }; let _ = unsafe { bar.val }; } + + #[clippy::msrv = "1.62"] + mod with_extern { + const extern "C" fn c() {} + //~^ ERROR: this could be a `const fn` + + #[rustfmt::skip] + const extern fn implicit_c() {} + //~^ ERROR: this could be a `const fn` + + // any item functions in extern block won't trigger this lint + extern "C" { + fn c_in_block(); + } + } } mod issue12677 { diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 58e639cc7fd..4d19c4d7a48 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -140,6 +140,21 @@ mod msrv { let bar = Bar { val: 1 }; let _ = unsafe { bar.val }; } + + #[clippy::msrv = "1.62"] + mod with_extern { + extern "C" fn c() {} + //~^ ERROR: this could be a `const fn` + + #[rustfmt::skip] + extern fn implicit_c() {} + //~^ ERROR: this could be a `const fn` + + // any item functions in extern block won't trigger this lint + extern "C" { + fn c_in_block(); + } + } } mod issue12677 { diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index 8999af761e3..ab36e0a281a 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -200,7 +200,29 @@ LL | const fn union_access_can_be_const() { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:152:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:146:9 + | +LL | extern "C" fn c() {} + | ^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | const extern "C" fn c() {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:150:9 + | +LL | extern fn implicit_c() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | const extern fn implicit_c() {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:167:9 | LL | / pub fn new(strings: Vec) -> Self { LL | | Self { strings } @@ -213,7 +235,7 @@ LL | pub const fn new(strings: Vec) -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:157:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:172:9 | LL | / pub fn empty() -> Self { LL | | Self { strings: Vec::new() } @@ -226,7 +248,7 @@ LL | pub const fn empty() -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:168:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:183:9 | LL | / pub fn new(text: String) -> Self { LL | | let vec = Vec::new(); @@ -239,5 +261,5 @@ help: make the function `const` LL | pub const fn new(text: String) -> Self { | +++++ -error: aborting due to 17 previous errors +error: aborting due to 19 previous errors diff --git a/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed b/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed new file mode 100644 index 00000000000..c103db536ab --- /dev/null +++ b/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed @@ -0,0 +1,14 @@ +#![warn(clippy::missing_const_for_fn)] +#![allow(unsupported_calling_conventions)] +#![feature(const_extern_fn)] + +const extern "C-unwind" fn c_unwind() {} +//~^ ERROR: this could be a `const fn` +const extern "system" fn system() {} +//~^ ERROR: this could be a `const fn` +const extern "system-unwind" fn system_unwind() {} +//~^ ERROR: this could be a `const fn` +pub const extern "stdcall" fn std_call() {} +//~^ ERROR: this could be a `const fn` +pub const extern "stdcall-unwind" fn std_call_unwind() {} +//~^ ERROR: this could be a `const fn` diff --git a/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs b/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs new file mode 100644 index 00000000000..0f7020ae559 --- /dev/null +++ b/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs @@ -0,0 +1,14 @@ +#![warn(clippy::missing_const_for_fn)] +#![allow(unsupported_calling_conventions)] +#![feature(const_extern_fn)] + +extern "C-unwind" fn c_unwind() {} +//~^ ERROR: this could be a `const fn` +extern "system" fn system() {} +//~^ ERROR: this could be a `const fn` +extern "system-unwind" fn system_unwind() {} +//~^ ERROR: this could be a `const fn` +pub extern "stdcall" fn std_call() {} +//~^ ERROR: this could be a `const fn` +pub extern "stdcall-unwind" fn std_call_unwind() {} +//~^ ERROR: this could be a `const fn` diff --git a/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr b/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr new file mode 100644 index 00000000000..036094a367b --- /dev/null +++ b/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr @@ -0,0 +1,59 @@ +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:5:1 + | +LL | extern "C-unwind" fn c_unwind() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::missing_const_for_fn)]` +help: make the function `const` + | +LL | const extern "C-unwind" fn c_unwind() {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:7:1 + | +LL | extern "system" fn system() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | const extern "system" fn system() {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:9:1 + | +LL | extern "system-unwind" fn system_unwind() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | const extern "system-unwind" fn system_unwind() {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:11:1 + | +LL | pub extern "stdcall" fn std_call() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | pub const extern "stdcall" fn std_call() {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:13:1 + | +LL | pub extern "stdcall-unwind" fn std_call_unwind() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | pub const extern "stdcall-unwind" fn std_call_unwind() {} + | +++++ + +error: aborting due to 5 previous errors +