Fix typo (#15081)
Add missing word (attribute) after the `#[expect]` attribute.
changelog: [`allow_attributes`]: Fix typo in documentation
diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs
index a5e66ad..26f6bbc 100644
--- a/clippy_utils/src/msrvs.rs
+++ b/clippy_utils/src/msrvs.rs
@@ -42,6 +42,7 @@
1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
1,63,0 { CLONE_INTO, CONST_SLICE_FROM_REF }
1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_C_FN }
+ 1,61,0 { CONST_FN_TRAIT_BOUND }
1,60,0 { ABS_DIFF }
1,59,0 { THREAD_LOCAL_CONST_INIT }
1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF }
diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs
index e629012..05c24d7 100644
--- a/clippy_utils/src/qualify_min_const_fn.rs
+++ b/clippy_utils/src/qualify_min_const_fn.rs
@@ -32,6 +32,19 @@
for local in &body.local_decls {
check_ty(cx, local.ty, local.source_info.span, msrv)?;
}
+ if !msrv.meets(cx, msrvs::CONST_FN_TRAIT_BOUND)
+ && let Some(sized_did) = cx.tcx.lang_items().sized_trait()
+ && cx.tcx.param_env(def_id).caller_bounds().iter().any(|bound| {
+ bound
+ .as_trait_clause()
+ .is_some_and(|clause| clause.def_id() != sized_did)
+ })
+ {
+ return Err((
+ body.span,
+ "non-`Sized` trait clause before `const_fn_trait_bound` is stabilized".into(),
+ ));
+ }
// impl trait is gone in MIR, so check the return type manually
check_ty(
cx,
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 65eb2d5..95bf63e 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.fixed
+++ b/tests/ui/missing_const_for_fn/could_be_const.fixed
@@ -221,3 +221,60 @@
//~^ missing_const_for_fn
*x += 1;
}
+
+mod issue_15079 {
+ pub trait Trait {}
+
+ pub struct Struct<T: Trait> {
+ _t: Option<T>,
+ }
+
+ impl<T: Trait> Struct<T> {
+ #[clippy::msrv = "1.60"]
+ pub fn new_1_60() -> Self {
+ Self { _t: None }
+ }
+
+ #[clippy::msrv = "1.61"]
+ pub const fn new_1_61() -> Self {
+ //~^ missing_const_for_fn
+ Self { _t: None }
+ }
+ }
+
+ pub struct S2<T> {
+ _t: Option<T>,
+ }
+
+ impl<T> S2<T> {
+ #[clippy::msrv = "1.60"]
+ pub const fn new_1_60() -> Self {
+ //~^ missing_const_for_fn
+ Self { _t: None }
+ }
+
+ #[clippy::msrv = "1.61"]
+ pub const fn new_1_61() -> Self {
+ //~^ missing_const_for_fn
+ Self { _t: None }
+ }
+ }
+
+ pub struct S3<T: ?Sized + 'static> {
+ _t: Option<&'static T>,
+ }
+
+ impl<T: ?Sized + 'static> S3<T> {
+ #[clippy::msrv = "1.60"]
+ pub const fn new_1_60() -> Self {
+ //~^ missing_const_for_fn
+ Self { _t: None }
+ }
+
+ #[clippy::msrv = "1.61"]
+ pub const fn new_1_61() -> Self {
+ //~^ missing_const_for_fn
+ Self { _t: None }
+ }
+ }
+}
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 3690d2f..8290be6 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.rs
+++ b/tests/ui/missing_const_for_fn/could_be_const.rs
@@ -221,3 +221,60 @@
//~^ missing_const_for_fn
*x += 1;
}
+
+mod issue_15079 {
+ pub trait Trait {}
+
+ pub struct Struct<T: Trait> {
+ _t: Option<T>,
+ }
+
+ impl<T: Trait> Struct<T> {
+ #[clippy::msrv = "1.60"]
+ pub fn new_1_60() -> Self {
+ Self { _t: None }
+ }
+
+ #[clippy::msrv = "1.61"]
+ pub fn new_1_61() -> Self {
+ //~^ missing_const_for_fn
+ Self { _t: None }
+ }
+ }
+
+ pub struct S2<T> {
+ _t: Option<T>,
+ }
+
+ impl<T> S2<T> {
+ #[clippy::msrv = "1.60"]
+ pub fn new_1_60() -> Self {
+ //~^ missing_const_for_fn
+ Self { _t: None }
+ }
+
+ #[clippy::msrv = "1.61"]
+ pub fn new_1_61() -> Self {
+ //~^ missing_const_for_fn
+ Self { _t: None }
+ }
+ }
+
+ pub struct S3<T: ?Sized + 'static> {
+ _t: Option<&'static T>,
+ }
+
+ impl<T: ?Sized + 'static> S3<T> {
+ #[clippy::msrv = "1.60"]
+ pub fn new_1_60() -> Self {
+ //~^ missing_const_for_fn
+ Self { _t: None }
+ }
+
+ #[clippy::msrv = "1.61"]
+ pub fn new_1_61() -> Self {
+ //~^ missing_const_for_fn
+ Self { _t: None }
+ }
+ }
+}
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 10e07d1..17cbc43 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.stderr
+++ b/tests/ui/missing_const_for_fn/could_be_const.stderr
@@ -332,5 +332,75 @@
LL | const fn mut_add(x: &mut i32) {
| +++++
-error: aborting due to 25 previous errors
+error: this could be a `const fn`
+ --> tests/ui/missing_const_for_fn/could_be_const.rs:239:9
+ |
+LL | / pub fn new_1_61() -> Self {
+LL | |
+LL | | Self { _t: None }
+LL | | }
+ | |_________^
+ |
+help: make the function `const`
+ |
+LL | pub const fn new_1_61() -> Self {
+ | +++++
+
+error: this could be a `const fn`
+ --> tests/ui/missing_const_for_fn/could_be_const.rs:251:9
+ |
+LL | / pub fn new_1_60() -> Self {
+LL | |
+LL | | Self { _t: None }
+LL | | }
+ | |_________^
+ |
+help: make the function `const`
+ |
+LL | pub const fn new_1_60() -> Self {
+ | +++++
+
+error: this could be a `const fn`
+ --> tests/ui/missing_const_for_fn/could_be_const.rs:257:9
+ |
+LL | / pub fn new_1_61() -> Self {
+LL | |
+LL | | Self { _t: None }
+LL | | }
+ | |_________^
+ |
+help: make the function `const`
+ |
+LL | pub const fn new_1_61() -> Self {
+ | +++++
+
+error: this could be a `const fn`
+ --> tests/ui/missing_const_for_fn/could_be_const.rs:269:9
+ |
+LL | / pub fn new_1_60() -> Self {
+LL | |
+LL | | Self { _t: None }
+LL | | }
+ | |_________^
+ |
+help: make the function `const`
+ |
+LL | pub const fn new_1_60() -> Self {
+ | +++++
+
+error: this could be a `const fn`
+ --> tests/ui/missing_const_for_fn/could_be_const.rs:275:9
+ |
+LL | / pub fn new_1_61() -> Self {
+LL | |
+LL | | Self { _t: None }
+LL | | }
+ | |_________^
+ |
+help: make the function `const`
+ |
+LL | pub const fn new_1_61() -> Self {
+ | +++++
+
+error: aborting due to 30 previous errors