about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_config/src/msrvs.rs2
-rw-r--r--clippy_lints/src/missing_const_for_fn.rs16
-rw-r--r--tests/ui/missing_const_for_fn/cant_be_const.rs9
-rw-r--r--tests/ui/missing_const_for_fn/could_be_const.fixed15
-rw-r--r--tests/ui/missing_const_for_fn/could_be_const.rs15
-rw-r--r--tests/ui/missing_const_for_fn/could_be_const.stderr30
-rw-r--r--tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed14
-rw-r--r--tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs14
-rw-r--r--tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr59
9 files changed, 168 insertions, 6 deletions
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<String>) -> Self {
 LL | |             Self { strings }
@@ -213,7 +235,7 @@ LL |         pub const fn new(strings: Vec<String>) -> 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
+