Rollup merge of #93926 - PatchMixolydic:bugfix/must_use-on-exprs, r=cjgillot
Lint against more useless `#[must_use]` attributes This expands the existing `#[must_use]` check in `unused_attributes` to lint against pretty much everything `#[must_use]` doesn't support. Fixes #93906.
This commit is contained in:
commit
daed86445d
@ -587,7 +587,6 @@ fn build_format(&self, input: &str, span: proc_macro2::Span) -> proc_macro2::Tok
|
||||
// next call to `it.next()` retrieves the next character.
|
||||
while let Some(c) = it.next() {
|
||||
if c == '{' && *it.peek().unwrap_or(&'\0') != '{' {
|
||||
#[must_use]
|
||||
let mut eat_argument = || -> Option<String> {
|
||||
let mut result = String::new();
|
||||
// Format specifiers look like
|
||||
|
@ -1111,7 +1111,7 @@ fn check_pass_by_value(&self, attr: &Attribute, span: Span, target: Target) -> b
|
||||
}
|
||||
|
||||
/// Warns against some misuses of `#[must_use]`
|
||||
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, _target: Target) -> bool {
|
||||
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
|
||||
let node = self.tcx.hir().get(hir_id);
|
||||
if let Some(fn_node) = node.fn_kind() {
|
||||
if let rustc_hir::IsAsync::Async = fn_node.asyncness() {
|
||||
@ -1131,6 +1131,39 @@ fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, _target: T
|
||||
}
|
||||
}
|
||||
|
||||
if !matches!(
|
||||
target,
|
||||
Target::Fn
|
||||
| Target::Enum
|
||||
| Target::Struct
|
||||
| Target::Union
|
||||
| Target::Method(_)
|
||||
| Target::ForeignFn
|
||||
// `impl Trait` in return position can trip
|
||||
// `unused_must_use` if `Trait` is marked as
|
||||
// `#[must_use]`
|
||||
| Target::Trait
|
||||
) {
|
||||
let article = match target {
|
||||
Target::ExternCrate
|
||||
| Target::OpaqueTy
|
||||
| Target::Enum
|
||||
| Target::Impl
|
||||
| Target::Expression
|
||||
| Target::Arm
|
||||
| Target::AssocConst
|
||||
| Target::AssocTy => "an",
|
||||
_ => "a",
|
||||
};
|
||||
|
||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||
lint.build(&format!(
|
||||
"`#[must_use]` has no effect when applied to {article} {target}"
|
||||
))
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
|
||||
// For now, its always valid
|
||||
true
|
||||
}
|
||||
|
@ -71,6 +71,7 @@
|
||||
//~^^ WARN this was previously accepted by the compiler
|
||||
// see issue-43106-gating-of-rustc_deprecated.rs
|
||||
#![must_use]
|
||||
//~^ WARN `#[must_use]` has no effect
|
||||
// see issue-43106-gating-of-stable.rs
|
||||
// see issue-43106-gating-of-unstable.rs
|
||||
// see issue-43106-gating-of-deprecated.rs
|
||||
@ -597,17 +598,17 @@ mod inner { #![deprecated] }
|
||||
#[deprecated] impl super::StructForDeprecated { }
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[must_use] //~ WARN `#[must_use]` has no effect
|
||||
mod must_use {
|
||||
mod inner { #![must_use] }
|
||||
mod inner { #![must_use] } //~ WARN `#[must_use]` has no effect
|
||||
|
||||
#[must_use] fn f() { }
|
||||
|
||||
#[must_use] struct S;
|
||||
|
||||
#[must_use] type T = S;
|
||||
#[must_use] type T = S; //~ WARN `#[must_use]` has no effect
|
||||
|
||||
#[must_use] impl S { }
|
||||
#[must_use] impl S { } //~ WARN `#[must_use]` has no effect
|
||||
}
|
||||
|
||||
#[windows_subsystem = "windows"]
|
||||
|
File diff suppressed because it is too large
Load Diff
125
src/test/ui/lint/unused/unused_attributes-must_use.rs
Normal file
125
src/test/ui/lint/unused/unused_attributes-must_use.rs
Normal file
@ -0,0 +1,125 @@
|
||||
#![allow(dead_code, path_statements)]
|
||||
#![deny(unused_attributes, unused_must_use)]
|
||||
#![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)]
|
||||
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
extern crate std as std2;
|
||||
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
mod test_mod {}
|
||||
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
use std::arch::global_asm;
|
||||
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
const CONST: usize = 4;
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
#[no_mangle]
|
||||
static STATIC: usize = 4;
|
||||
|
||||
#[must_use]
|
||||
struct X;
|
||||
|
||||
#[must_use]
|
||||
enum Y {
|
||||
Z,
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
union U {
|
||||
unit: (),
|
||||
}
|
||||
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
impl U {
|
||||
#[must_use]
|
||||
fn method() -> i32 {
|
||||
4
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[no_mangle]
|
||||
fn foo() -> i64 {
|
||||
4
|
||||
}
|
||||
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
extern "Rust" {
|
||||
#[link_name = "STATIC"]
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
static FOREIGN_STATIC: usize;
|
||||
|
||||
#[link_name = "foo"]
|
||||
#[must_use]
|
||||
fn foreign_foo() -> i64;
|
||||
}
|
||||
|
||||
#[must_use] //~ ERROR unused attribute
|
||||
global_asm!("");
|
||||
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
type UseMe = ();
|
||||
|
||||
fn qux<#[must_use] T>(_: T) {} //~ ERROR `#[must_use]` has no effect
|
||||
|
||||
#[must_use]
|
||||
trait Use {
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
const ASSOC_CONST: usize = 4;
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
type AssocTy;
|
||||
|
||||
#[must_use]
|
||||
fn get_four(&self) -> usize {
|
||||
4
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
impl Use for () {
|
||||
type AssocTy = ();
|
||||
}
|
||||
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
trait Alias = Use;
|
||||
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
macro_rules! cool_macro {
|
||||
() => {
|
||||
4
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
let x = || {};
|
||||
x();
|
||||
|
||||
let x = #[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
|| {};
|
||||
x();
|
||||
|
||||
X; //~ ERROR that must be used
|
||||
Y::Z; //~ ERROR that must be used
|
||||
U { unit: () }; //~ ERROR that must be used
|
||||
U::method(); //~ ERROR that must be used
|
||||
foo(); //~ ERROR that must be used
|
||||
|
||||
unsafe {
|
||||
foreign_foo(); //~ ERROR that must be used
|
||||
};
|
||||
|
||||
CONST;
|
||||
STATIC;
|
||||
unsafe { FOREIGN_STATIC };
|
||||
cool_macro!();
|
||||
qux(4);
|
||||
().get_four(); //~ ERROR that must be used
|
||||
|
||||
match Some(4) {
|
||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||
Some(res) => res,
|
||||
None => 0,
|
||||
};
|
||||
}
|
175
src/test/ui/lint/unused/unused_attributes-must_use.stderr
Normal file
175
src/test/ui/lint/unused/unused_attributes-must_use.stderr
Normal file
@ -0,0 +1,175 @@
|
||||
error: unused attribute `must_use`
|
||||
--> $DIR/unused_attributes-must_use.rs:58:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused_attributes-must_use.rs:2:9
|
||||
|
|
||||
LL | #![deny(unused_attributes, unused_must_use)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
note: the built-in attribute `must_use` will be ignored, since it's applied to the macro invocation `global_asm`
|
||||
--> $DIR/unused_attributes-must_use.rs:59:1
|
||||
|
|
||||
LL | global_asm!("");
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to an extern crate
|
||||
--> $DIR/unused_attributes-must_use.rs:5:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a module
|
||||
--> $DIR/unused_attributes-must_use.rs:8:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a use
|
||||
--> $DIR/unused_attributes-must_use.rs:11:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a constant item
|
||||
--> $DIR/unused_attributes-must_use.rs:14:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a static item
|
||||
--> $DIR/unused_attributes-must_use.rs:16:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to an item
|
||||
--> $DIR/unused_attributes-must_use.rs:33:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a foreign module
|
||||
--> $DIR/unused_attributes-must_use.rs:47:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a type alias
|
||||
--> $DIR/unused_attributes-must_use.rs:61:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a type parameter
|
||||
--> $DIR/unused_attributes-must_use.rs:64:8
|
||||
|
|
||||
LL | fn qux<#[must_use] T>(_: T) {}
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to an item
|
||||
--> $DIR/unused_attributes-must_use.rs:79:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a trait alias
|
||||
--> $DIR/unused_attributes-must_use.rs:84:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a macro def
|
||||
--> $DIR/unused_attributes-must_use.rs:87:1
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a statement
|
||||
--> $DIR/unused_attributes-must_use.rs:95:5
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a closure
|
||||
--> $DIR/unused_attributes-must_use.rs:99:13
|
||||
|
|
||||
LL | let x = #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to an match arm
|
||||
--> $DIR/unused_attributes-must_use.rs:121:9
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to an associated const
|
||||
--> $DIR/unused_attributes-must_use.rs:68:5
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to an associated type
|
||||
--> $DIR/unused_attributes-must_use.rs:70:5
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a foreign static item
|
||||
--> $DIR/unused_attributes-must_use.rs:50:5
|
||||
|
|
||||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: unused `X` that must be used
|
||||
--> $DIR/unused_attributes-must_use.rs:103:5
|
||||
|
|
||||
LL | X;
|
||||
| ^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused_attributes-must_use.rs:2:28
|
||||
|
|
||||
LL | #![deny(unused_attributes, unused_must_use)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused `Y` that must be used
|
||||
--> $DIR/unused_attributes-must_use.rs:104:5
|
||||
|
|
||||
LL | Y::Z;
|
||||
| ^^^^^
|
||||
|
||||
error: unused `U` that must be used
|
||||
--> $DIR/unused_attributes-must_use.rs:105:5
|
||||
|
|
||||
LL | U { unit: () };
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused return value of `U::method` that must be used
|
||||
--> $DIR/unused_attributes-must_use.rs:106:5
|
||||
|
|
||||
LL | U::method();
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: unused return value of `foo` that must be used
|
||||
--> $DIR/unused_attributes-must_use.rs:107:5
|
||||
|
|
||||
LL | foo();
|
||||
| ^^^^^^
|
||||
|
||||
error: unused return value of `foreign_foo` that must be used
|
||||
--> $DIR/unused_attributes-must_use.rs:110:9
|
||||
|
|
||||
LL | foreign_foo();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused return value of `Use::get_four` that must be used
|
||||
--> $DIR/unused_attributes-must_use.rs:118:5
|
||||
|
|
||||
LL | ().get_four();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 26 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user