Extend #[must_use] lint to arrays
This commit is contained in:
parent
400fd6055f
commit
76f5b50716
@ -48,7 +48,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let ty = cx.tables.expr_ty(&expr);
|
let ty = cx.tables.expr_ty(&expr);
|
||||||
let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "");
|
let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", false);
|
||||||
|
|
||||||
let mut fn_warned = false;
|
let mut fn_warned = false;
|
||||||
let mut op_warned = false;
|
let mut op_warned = false;
|
||||||
@ -133,8 +133,9 @@ fn check_must_use_ty<'tcx>(
|
|||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
expr: &hir::Expr,
|
expr: &hir::Expr,
|
||||||
span: Span,
|
span: Span,
|
||||||
descr_pre_path: &str,
|
descr_pre: &str,
|
||||||
descr_post_path: &str,
|
descr_post: &str,
|
||||||
|
plural: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(
|
if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(
|
||||||
cx.tcx.hir().get_module_parent(expr.hir_id), ty)
|
cx.tcx.hir().get_module_parent(expr.hir_id), ty)
|
||||||
@ -142,14 +143,16 @@ fn check_must_use_ty<'tcx>(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let plural_suffix = if plural { "s" } else { "" };
|
||||||
|
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::Adt(..) if ty.is_box() => {
|
ty::Adt(..) if ty.is_box() => {
|
||||||
let boxed_ty = ty.boxed_ty();
|
let boxed_ty = ty.boxed_ty();
|
||||||
let descr_pre_path = &format!("{}boxed ", descr_pre_path);
|
let descr_pre = &format!("{}boxed ", descr_pre);
|
||||||
check_must_use_ty(cx, boxed_ty, expr, span, descr_pre_path, descr_post_path)
|
check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural)
|
||||||
}
|
}
|
||||||
ty::Adt(def, _) => {
|
ty::Adt(def, _) => {
|
||||||
check_must_use_def(cx, def.did, span, descr_pre_path, descr_post_path)
|
check_must_use_def(cx, def.did, span, descr_pre, descr_post)
|
||||||
}
|
}
|
||||||
ty::Opaque(def, _) => {
|
ty::Opaque(def, _) => {
|
||||||
let mut has_emitted = false;
|
let mut has_emitted = false;
|
||||||
@ -157,8 +160,12 @@ fn check_must_use_ty<'tcx>(
|
|||||||
if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate {
|
if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate {
|
||||||
let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
|
let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
|
||||||
let def_id = trait_ref.def_id;
|
let def_id = trait_ref.def_id;
|
||||||
let descr_pre = &format!("{}implementer of ", descr_pre_path);
|
let descr_pre = &format!(
|
||||||
if check_must_use_def(cx, def_id, span, descr_pre, descr_post_path) {
|
"{}implementer{} of ",
|
||||||
|
descr_pre,
|
||||||
|
plural_suffix,
|
||||||
|
);
|
||||||
|
if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
|
||||||
has_emitted = true;
|
has_emitted = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -171,8 +178,12 @@ fn check_must_use_ty<'tcx>(
|
|||||||
for predicate in binder.skip_binder().iter() {
|
for predicate in binder.skip_binder().iter() {
|
||||||
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate {
|
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate {
|
||||||
let def_id = trait_ref.def_id;
|
let def_id = trait_ref.def_id;
|
||||||
let descr_post = &format!(" trait object{}", descr_post_path);
|
let descr_post = &format!(
|
||||||
if check_must_use_def(cx, def_id, span, descr_pre_path, descr_post) {
|
" trait object{}{}",
|
||||||
|
plural_suffix,
|
||||||
|
descr_post,
|
||||||
|
);
|
||||||
|
if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
|
||||||
has_emitted = true;
|
has_emitted = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -189,14 +200,27 @@ fn check_must_use_ty<'tcx>(
|
|||||||
vec![]
|
vec![]
|
||||||
};
|
};
|
||||||
for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() {
|
for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() {
|
||||||
let descr_post_path = &format!(" in tuple element {}", i);
|
let descr_post = &format!(" in tuple element {}", i);
|
||||||
let span = *spans.get(i).unwrap_or(&span);
|
let span = *spans.get(i).unwrap_or(&span);
|
||||||
if check_must_use_ty(cx, ty, expr, span, descr_pre_path, descr_post_path) {
|
if check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, plural) {
|
||||||
has_emitted = true;
|
has_emitted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
has_emitted
|
has_emitted
|
||||||
}
|
}
|
||||||
|
ty::Array(ty, len) => match len.assert_usize(cx.tcx) {
|
||||||
|
// If the array is definitely non-empty, we can do `#[must_use]` checking.
|
||||||
|
Some(n) if n != 0 => {
|
||||||
|
let descr_pre = &format!(
|
||||||
|
"{}array{} of ",
|
||||||
|
descr_pre,
|
||||||
|
plural_suffix,
|
||||||
|
);
|
||||||
|
check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, true)
|
||||||
|
}
|
||||||
|
// Otherwise, we don't lint, to avoid false positives.
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
47
src/test/ui/lint/must_use-array.rs
Normal file
47
src/test/ui/lint/must_use-array.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#![deny(unused_must_use)]
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
struct A;
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
trait T {}
|
||||||
|
|
||||||
|
impl T for A {}
|
||||||
|
|
||||||
|
fn empty() -> [S; 0] {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn singleton() -> [S; 1] {
|
||||||
|
[S]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn many() -> [S; 4] {
|
||||||
|
[S, S, S, S]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn array_of_impl_trait() -> [impl T; 2] {
|
||||||
|
[A, A]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn impl_array() -> [(u8, Box<dyn T>); 2] {
|
||||||
|
[(0, Box::new(A)), (0, Box::new(A))]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn array_of_arrays_of_arrays() -> [[[S; 1]; 2]; 1] {
|
||||||
|
[[[S], [S]]]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
empty(); // ok
|
||||||
|
singleton(); //~ ERROR unused array of `S` that must be used
|
||||||
|
many(); //~ ERROR unused array of `S` that must be used
|
||||||
|
([S], 0, ()); //~ ERROR unused array of `S` in tuple element 0 that must be used
|
||||||
|
array_of_impl_trait(); //~ ERROR unused array of implementers of `T` that must be used
|
||||||
|
impl_array();
|
||||||
|
//~^ ERROR unused array of boxed `T` trait objects in tuple element 1 that must be used
|
||||||
|
array_of_arrays_of_arrays();
|
||||||
|
//~^ ERROR unused array of arrays of arrays of `S` that must be used
|
||||||
|
}
|
44
src/test/ui/lint/must_use-array.stderr
Normal file
44
src/test/ui/lint/must_use-array.stderr
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
error: unused array of `S` that must be used
|
||||||
|
--> $DIR/must_use-array.rs:39:5
|
||||||
|
|
|
||||||
|
LL | singleton();
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: lint level defined here
|
||||||
|
--> $DIR/must_use-array.rs:1:9
|
||||||
|
|
|
||||||
|
LL | #![deny(unused_must_use)]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unused array of `S` that must be used
|
||||||
|
--> $DIR/must_use-array.rs:40:5
|
||||||
|
|
|
||||||
|
LL | many();
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: unused array of `S` in tuple element 0 that must be used
|
||||||
|
--> $DIR/must_use-array.rs:41:6
|
||||||
|
|
|
||||||
|
LL | ([S], 0, ());
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: unused array of implementers of `T` that must be used
|
||||||
|
--> $DIR/must_use-array.rs:42:5
|
||||||
|
|
|
||||||
|
LL | array_of_impl_trait();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unused array of boxed `T` trait objects in tuple element 1 that must be used
|
||||||
|
--> $DIR/must_use-array.rs:43:5
|
||||||
|
|
|
||||||
|
LL | impl_array();
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unused array of arrays of arrays of `S` that must be used
|
||||||
|
--> $DIR/must_use-array.rs:45:5
|
||||||
|
|
|
||||||
|
LL | array_of_arrays_of_arrays();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
Loading…
Reference in New Issue
Block a user