mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
Refactor must_use
lint into two parts
Before, the lint did the checking for `must_use` and pretty printing the types in a special format in one pass, causing quite complex and untranslatable code. Now the collection and printing is split in two. That should also make it easier to translate or extract the type pretty printing in the future. Also fixes an integer overflow in the array length pluralization calculation.
This commit is contained in:
parent
62c627c7a3
commit
4e9ceef76d
@ -13,6 +13,7 @@ use rustc_middle::ty::{self, DefIdTree, Ty};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::{BytePos, Span};
|
||||
use std::iter;
|
||||
|
||||
declare_lint! {
|
||||
/// The `unused_must_use` lint detects unused result of a type flagged as
|
||||
@ -113,30 +114,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
}
|
||||
|
||||
let ty = cx.typeck_results().expr_ty(&expr);
|
||||
let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, expr.span, "", "", 1);
|
||||
|
||||
let mut fn_warned = false;
|
||||
let mut op_warned = false;
|
||||
let maybe_def_id = match expr.kind {
|
||||
hir::ExprKind::Call(ref callee, _) => {
|
||||
match callee.kind {
|
||||
hir::ExprKind::Path(ref qpath) => {
|
||||
match cx.qpath_res(qpath, callee.hir_id) {
|
||||
Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
|
||||
// `Res::Local` if it was a closure, for which we
|
||||
// do not currently support must-use linting
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span);
|
||||
let type_lint_emitted_or_suppressed = match must_use_result {
|
||||
Some(path) => {
|
||||
emit_must_use_untranslated(cx, &path, "", "", 1);
|
||||
true
|
||||
}
|
||||
hir::ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
|
||||
_ => None,
|
||||
None => false,
|
||||
};
|
||||
if let Some(def_id) = maybe_def_id {
|
||||
fn_warned = check_must_use_def(cx, def_id, expr.span, "return value of ", "");
|
||||
} else if type_permits_lack_of_use {
|
||||
|
||||
let fn_warned = check_fn_must_use(cx, expr);
|
||||
|
||||
if !fn_warned && type_lint_emitted_or_suppressed {
|
||||
// We don't warn about unused unit or uninhabited types.
|
||||
// (See https://github.com/rust-lang/rust/issues/43806 for details.)
|
||||
return;
|
||||
@ -170,6 +160,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let mut op_warned = false;
|
||||
|
||||
if let Some(must_use_op) = must_use_op {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, expr.span, fluent::lint_unused_op, |lint| {
|
||||
lint.set_arg("op", must_use_op)
|
||||
@ -184,22 +176,64 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
op_warned = true;
|
||||
}
|
||||
|
||||
if !(type_permits_lack_of_use || fn_warned || op_warned) {
|
||||
if !(type_lint_emitted_or_suppressed || fn_warned || op_warned) {
|
||||
cx.struct_span_lint(UNUSED_RESULTS, s.span, fluent::lint_unused_result, |lint| {
|
||||
lint.set_arg("ty", ty)
|
||||
});
|
||||
}
|
||||
|
||||
// Returns whether an error has been emitted (and thus another does not need to be later).
|
||||
fn check_must_use_ty<'tcx>(
|
||||
fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
|
||||
let maybe_def_id = match expr.kind {
|
||||
hir::ExprKind::Call(ref callee, _) => {
|
||||
match callee.kind {
|
||||
hir::ExprKind::Path(ref qpath) => {
|
||||
match cx.qpath_res(qpath, callee.hir_id) {
|
||||
Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
|
||||
// `Res::Local` if it was a closure, for which we
|
||||
// do not currently support must-use linting
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
hir::ExprKind::MethodCall(..) => {
|
||||
cx.typeck_results().type_dependent_def_id(expr.hir_id)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
if let Some(def_id) = maybe_def_id {
|
||||
check_must_use_def(cx, def_id, expr.span, "return value of ", "")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// A path through a type to a must_use source. Contains useful info for the lint.
|
||||
#[derive(Debug)]
|
||||
enum MustUsePath {
|
||||
/// Suppress must_use checking.
|
||||
Suppressed,
|
||||
/// The root of the normal must_use lint with an optional message.
|
||||
Def(Span, DefId, Option<Symbol>),
|
||||
Boxed(Box<Self>),
|
||||
Opaque(Box<Self>),
|
||||
TraitObject(Box<Self>),
|
||||
TupleElement(Vec<(usize, Self)>),
|
||||
Array(Box<Self>, u64),
|
||||
/// The root of the unused_closures lint.
|
||||
Closure(Span),
|
||||
/// The root of the unused_generators lint.
|
||||
Generator(Span),
|
||||
}
|
||||
|
||||
#[instrument(skip(cx, expr), level = "debug", ret)]
|
||||
fn is_ty_must_use<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
expr: &hir::Expr<'_>,
|
||||
span: Span,
|
||||
descr_pre: &str,
|
||||
descr_post: &str,
|
||||
plural_len: usize,
|
||||
) -> bool {
|
||||
) -> Option<MustUsePath> {
|
||||
if ty.is_unit()
|
||||
|| cx.tcx.is_ty_uninhabited_from(
|
||||
cx.tcx.parent_module(expr.hir_id).to_def_id(),
|
||||
@ -207,87 +241,164 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
cx.param_env,
|
||||
)
|
||||
{
|
||||
return true;
|
||||
return Some(MustUsePath::Suppressed);
|
||||
}
|
||||
|
||||
let plural_suffix = pluralize!(plural_len);
|
||||
|
||||
match *ty.kind() {
|
||||
ty::Adt(..) if ty.is_box() => {
|
||||
let boxed_ty = ty.boxed_ty();
|
||||
let descr_pre = &format!("{}boxed ", descr_pre);
|
||||
check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural_len)
|
||||
is_ty_must_use(cx, boxed_ty, expr, span)
|
||||
.map(|inner| MustUsePath::Boxed(Box::new(inner)))
|
||||
}
|
||||
ty::Adt(def, _) => check_must_use_def(cx, def.did(), span, descr_pre, descr_post),
|
||||
ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
|
||||
ty::Opaque(def, _) => {
|
||||
let mut has_emitted = false;
|
||||
for obligation in elaborate_predicates_with_span(
|
||||
elaborate_predicates_with_span(
|
||||
cx.tcx,
|
||||
cx.tcx.explicit_item_bounds(def).iter().cloned(),
|
||||
) {
|
||||
)
|
||||
.filter_map(|obligation| {
|
||||
// We only look at the `DefId`, so it is safe to skip the binder here.
|
||||
if let ty::PredicateKind::Trait(ref poly_trait_predicate) =
|
||||
obligation.predicate.kind().skip_binder()
|
||||
{
|
||||
let def_id = poly_trait_predicate.trait_ref.def_id;
|
||||
let descr_pre =
|
||||
&format!("{}implementer{} of ", descr_pre, plural_suffix,);
|
||||
if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
|
||||
has_emitted = true;
|
||||
break;
|
||||
}
|
||||
|
||||
is_def_must_use(cx, def_id, span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
has_emitted
|
||||
})
|
||||
.map(|inner| MustUsePath::Opaque(Box::new(inner)))
|
||||
.next()
|
||||
}
|
||||
ty::Dynamic(binder, _, _) => {
|
||||
let mut has_emitted = false;
|
||||
for predicate in binder.iter() {
|
||||
ty::Dynamic(binders, _, _) => binders
|
||||
.iter()
|
||||
.filter_map(|predicate| {
|
||||
if let ty::ExistentialPredicate::Trait(ref trait_ref) =
|
||||
predicate.skip_binder()
|
||||
{
|
||||
let def_id = trait_ref.def_id;
|
||||
let descr_post =
|
||||
&format!(" trait object{}{}", plural_suffix, descr_post,);
|
||||
if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
|
||||
has_emitted = true;
|
||||
break;
|
||||
}
|
||||
is_def_must_use(cx, def_id, span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
has_emitted
|
||||
}
|
||||
ty::Tuple(ref tys) => {
|
||||
let mut has_emitted = false;
|
||||
let comps = if let hir::ExprKind::Tup(comps) = expr.kind {
|
||||
debug_assert_eq!(comps.len(), tys.len());
|
||||
comps
|
||||
.map(|inner| MustUsePath::TraitObject(Box::new(inner)))
|
||||
})
|
||||
.next(),
|
||||
ty::Tuple(tys) => {
|
||||
let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind {
|
||||
debug_assert_eq!(elem_exprs.len(), tys.len());
|
||||
elem_exprs
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
for (i, ty) in tys.iter().enumerate() {
|
||||
let descr_post = &format!(" in tuple element {}", i);
|
||||
let e = comps.get(i).unwrap_or(expr);
|
||||
let span = e.span;
|
||||
if check_must_use_ty(cx, ty, e, span, descr_pre, descr_post, plural_len) {
|
||||
has_emitted = true;
|
||||
}
|
||||
|
||||
// Default to `expr`.
|
||||
let elem_exprs = elem_exprs.iter().chain(iter::repeat(expr));
|
||||
|
||||
let nested_must_use = tys
|
||||
.iter()
|
||||
.zip(elem_exprs)
|
||||
.enumerate()
|
||||
.filter_map(|(i, (ty, expr))| {
|
||||
is_ty_must_use(cx, ty, expr, expr.span).map(|path| (i, path))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !nested_must_use.is_empty() {
|
||||
Some(MustUsePath::TupleElement(nested_must_use))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
has_emitted
|
||||
}
|
||||
ty::Array(ty, len) => match len.try_eval_usize(cx.tcx, cx.param_env) {
|
||||
// If the array is empty we don't lint, to avoid false positives
|
||||
Some(0) | None => false,
|
||||
Some(0) | None => None,
|
||||
// If the array is definitely non-empty, we can do `#[must_use]` checking.
|
||||
Some(n) => {
|
||||
let descr_pre = &format!("{}array{} of ", descr_pre, plural_suffix,);
|
||||
check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, n as usize + 1)
|
||||
}
|
||||
Some(len) => is_ty_must_use(cx, ty, expr, span)
|
||||
.map(|inner| MustUsePath::Array(Box::new(inner), len)),
|
||||
},
|
||||
ty::Closure(..) => {
|
||||
ty::Closure(..) => Some(MustUsePath::Closure(span)),
|
||||
ty::Generator(..) => Some(MustUsePath::Generator(span)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_def_must_use(cx: &LateContext<'_>, def_id: DefId, span: Span) -> Option<MustUsePath> {
|
||||
if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
|
||||
// check for #[must_use = "..."]
|
||||
let reason = attr.value_str();
|
||||
Some(MustUsePath::Def(span, def_id, reason))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether further errors should be suppressed because either a lint has been emitted or the type should be ignored.
|
||||
fn check_must_use_def(
|
||||
cx: &LateContext<'_>,
|
||||
def_id: DefId,
|
||||
span: Span,
|
||||
descr_pre_path: &str,
|
||||
descr_post_path: &str,
|
||||
) -> bool {
|
||||
is_def_must_use(cx, def_id, span)
|
||||
.map(|must_use_path| {
|
||||
emit_must_use_untranslated(
|
||||
cx,
|
||||
&must_use_path,
|
||||
descr_pre_path,
|
||||
descr_post_path,
|
||||
1,
|
||||
)
|
||||
})
|
||||
.is_some()
|
||||
}
|
||||
|
||||
#[instrument(skip(cx), level = "debug")]
|
||||
fn emit_must_use_untranslated(
|
||||
cx: &LateContext<'_>,
|
||||
path: &MustUsePath,
|
||||
descr_pre: &str,
|
||||
descr_post: &str,
|
||||
plural_len: usize,
|
||||
) {
|
||||
let plural_suffix = pluralize!(plural_len);
|
||||
|
||||
match path {
|
||||
MustUsePath::Suppressed => {}
|
||||
MustUsePath::Boxed(path) => {
|
||||
let descr_pre = &format!("{}boxed ", descr_pre);
|
||||
emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
|
||||
}
|
||||
MustUsePath::Opaque(path) => {
|
||||
let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix);
|
||||
emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
|
||||
}
|
||||
MustUsePath::TraitObject(path) => {
|
||||
let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post);
|
||||
emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
|
||||
}
|
||||
MustUsePath::TupleElement(elems) => {
|
||||
for (index, path) in elems {
|
||||
let descr_post = &format!(" in tuple element {}", index);
|
||||
emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
|
||||
}
|
||||
}
|
||||
MustUsePath::Array(path, len) => {
|
||||
let descr_pre = &format!("{}array{} of ", descr_pre, plural_suffix);
|
||||
emit_must_use_untranslated(
|
||||
cx,
|
||||
path,
|
||||
descr_pre,
|
||||
descr_post,
|
||||
plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)),
|
||||
);
|
||||
}
|
||||
MustUsePath::Closure(span) => {
|
||||
cx.struct_span_lint(
|
||||
UNUSED_MUST_USE,
|
||||
span,
|
||||
*span,
|
||||
fluent::lint_unused_closure,
|
||||
|lint| {
|
||||
// FIXME(davidtwco): this isn't properly translatable because of the
|
||||
@ -298,12 +409,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
.note(fluent::note)
|
||||
},
|
||||
);
|
||||
true
|
||||
}
|
||||
ty::Generator(..) => {
|
||||
MustUsePath::Generator(span) => {
|
||||
cx.struct_span_lint(
|
||||
UNUSED_MUST_USE,
|
||||
span,
|
||||
*span,
|
||||
fluent::lint_unused_generator,
|
||||
|lint| {
|
||||
// FIXME(davidtwco): this isn't properly translatable because of the
|
||||
@ -314,40 +424,20 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
.note(fluent::note)
|
||||
},
|
||||
);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether an error has been emitted (and thus another does not need to be later).
|
||||
// FIXME: Args desc_{pre,post}_path could be made lazy by taking Fn() -> &str, but this
|
||||
// would make calling it a big awkward. Could also take String (so args are moved), but
|
||||
// this would still require a copy into the format string, which would only be executed
|
||||
// when needed.
|
||||
fn check_must_use_def(
|
||||
cx: &LateContext<'_>,
|
||||
def_id: DefId,
|
||||
span: Span,
|
||||
descr_pre_path: &str,
|
||||
descr_post_path: &str,
|
||||
) -> bool {
|
||||
if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, span, fluent::lint_unused_def, |lint| {
|
||||
// FIXME(davidtwco): this isn't properly translatable because of the pre/post
|
||||
// strings
|
||||
lint.set_arg("pre", descr_pre_path);
|
||||
lint.set_arg("post", descr_post_path);
|
||||
lint.set_arg("def", cx.tcx.def_path_str(def_id));
|
||||
// check for #[must_use = "..."]
|
||||
if let Some(note) = attr.value_str() {
|
||||
lint.note(note.as_str());
|
||||
}
|
||||
lint
|
||||
});
|
||||
true
|
||||
} else {
|
||||
false
|
||||
MustUsePath::Def(span, def_id, reason) => {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, *span, fluent::lint_unused_def, |lint| {
|
||||
// FIXME(davidtwco): this isn't properly translatable because of the pre/post
|
||||
// strings
|
||||
lint.set_arg("pre", descr_pre);
|
||||
lint.set_arg("post", descr_post);
|
||||
lint.set_arg("def", cx.tcx.def_path_str(*def_id));
|
||||
if let Some(note) = reason {
|
||||
lint.note(note.as_str());
|
||||
}
|
||||
lint
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,18 @@
|
||||
// check-pass
|
||||
|
||||
#![warn(unused_must_use)]
|
||||
#![feature(never_type)]
|
||||
|
||||
fn deref_never(x: &!) {
|
||||
// Don't lint for uninhabited typess
|
||||
*x;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let val = 1;
|
||||
let val_pointer = &val;
|
||||
|
||||
// Comparison Operators
|
||||
// Comparison Operators
|
||||
val == 1; //~ WARNING unused comparison
|
||||
val < 1; //~ WARNING unused comparison
|
||||
val <= 1; //~ WARNING unused comparison
|
||||
@ -16,26 +22,30 @@ fn main() {
|
||||
val >= 1; //~ WARNING unused comparison
|
||||
val > 1; //~ WARNING unused comparison
|
||||
|
||||
// Arithmetic Operators
|
||||
// Arithmetic Operators
|
||||
val + 2; //~ WARNING unused arithmetic operation
|
||||
val - 2; //~ WARNING unused arithmetic operation
|
||||
val / 2; //~ WARNING unused arithmetic operation
|
||||
val * 2; //~ WARNING unused arithmetic operation
|
||||
val % 2; //~ WARNING unused arithmetic operation
|
||||
|
||||
// Logical Operators
|
||||
// Logical Operators
|
||||
true && true; //~ WARNING unused logical operation
|
||||
false || true; //~ WARNING unused logical operation
|
||||
|
||||
// Bitwise Operators
|
||||
// Bitwise Operators
|
||||
5 ^ val; //~ WARNING unused bitwise operation
|
||||
5 & val; //~ WARNING unused bitwise operation
|
||||
5 | val; //~ WARNING unused bitwise operation
|
||||
5 << val; //~ WARNING unused bitwise operation
|
||||
5 >> val; //~ WARNING unused bitwise operation
|
||||
|
||||
// Unary Operators
|
||||
// Unary Operators
|
||||
!val; //~ WARNING unused unary operation
|
||||
-val; //~ WARNING unused unary operation
|
||||
*val_pointer; //~ WARNING unused unary operation
|
||||
|
||||
if false {
|
||||
deref_never(&panic!());
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: unused comparison that must be used
|
||||
--> $DIR/must-use-ops.rs:12:5
|
||||
--> $DIR/must-use-ops.rs:18:5
|
||||
|
|
||||
LL | val == 1;
|
||||
| ^^^^^^^^ the comparison produces a value
|
||||
@ -15,7 +15,7 @@ LL | let _ = val == 1;
|
||||
| +++++++
|
||||
|
||||
warning: unused comparison that must be used
|
||||
--> $DIR/must-use-ops.rs:13:5
|
||||
--> $DIR/must-use-ops.rs:19:5
|
||||
|
|
||||
LL | val < 1;
|
||||
| ^^^^^^^ the comparison produces a value
|
||||
@ -26,7 +26,7 @@ LL | let _ = val < 1;
|
||||
| +++++++
|
||||
|
||||
warning: unused comparison that must be used
|
||||
--> $DIR/must-use-ops.rs:14:5
|
||||
--> $DIR/must-use-ops.rs:20:5
|
||||
|
|
||||
LL | val <= 1;
|
||||
| ^^^^^^^^ the comparison produces a value
|
||||
@ -37,7 +37,7 @@ LL | let _ = val <= 1;
|
||||
| +++++++
|
||||
|
||||
warning: unused comparison that must be used
|
||||
--> $DIR/must-use-ops.rs:15:5
|
||||
--> $DIR/must-use-ops.rs:21:5
|
||||
|
|
||||
LL | val != 1;
|
||||
| ^^^^^^^^ the comparison produces a value
|
||||
@ -48,7 +48,7 @@ LL | let _ = val != 1;
|
||||
| +++++++
|
||||
|
||||
warning: unused comparison that must be used
|
||||
--> $DIR/must-use-ops.rs:16:5
|
||||
--> $DIR/must-use-ops.rs:22:5
|
||||
|
|
||||
LL | val >= 1;
|
||||
| ^^^^^^^^ the comparison produces a value
|
||||
@ -59,7 +59,7 @@ LL | let _ = val >= 1;
|
||||
| +++++++
|
||||
|
||||
warning: unused comparison that must be used
|
||||
--> $DIR/must-use-ops.rs:17:5
|
||||
--> $DIR/must-use-ops.rs:23:5
|
||||
|
|
||||
LL | val > 1;
|
||||
| ^^^^^^^ the comparison produces a value
|
||||
@ -70,7 +70,7 @@ LL | let _ = val > 1;
|
||||
| +++++++
|
||||
|
||||
warning: unused arithmetic operation that must be used
|
||||
--> $DIR/must-use-ops.rs:20:5
|
||||
--> $DIR/must-use-ops.rs:26:5
|
||||
|
|
||||
LL | val + 2;
|
||||
| ^^^^^^^ the arithmetic operation produces a value
|
||||
@ -81,7 +81,7 @@ LL | let _ = val + 2;
|
||||
| +++++++
|
||||
|
||||
warning: unused arithmetic operation that must be used
|
||||
--> $DIR/must-use-ops.rs:21:5
|
||||
--> $DIR/must-use-ops.rs:27:5
|
||||
|
|
||||
LL | val - 2;
|
||||
| ^^^^^^^ the arithmetic operation produces a value
|
||||
@ -92,7 +92,7 @@ LL | let _ = val - 2;
|
||||
| +++++++
|
||||
|
||||
warning: unused arithmetic operation that must be used
|
||||
--> $DIR/must-use-ops.rs:22:5
|
||||
--> $DIR/must-use-ops.rs:28:5
|
||||
|
|
||||
LL | val / 2;
|
||||
| ^^^^^^^ the arithmetic operation produces a value
|
||||
@ -103,7 +103,7 @@ LL | let _ = val / 2;
|
||||
| +++++++
|
||||
|
||||
warning: unused arithmetic operation that must be used
|
||||
--> $DIR/must-use-ops.rs:23:5
|
||||
--> $DIR/must-use-ops.rs:29:5
|
||||
|
|
||||
LL | val * 2;
|
||||
| ^^^^^^^ the arithmetic operation produces a value
|
||||
@ -114,7 +114,7 @@ LL | let _ = val * 2;
|
||||
| +++++++
|
||||
|
||||
warning: unused arithmetic operation that must be used
|
||||
--> $DIR/must-use-ops.rs:24:5
|
||||
--> $DIR/must-use-ops.rs:30:5
|
||||
|
|
||||
LL | val % 2;
|
||||
| ^^^^^^^ the arithmetic operation produces a value
|
||||
@ -125,7 +125,7 @@ LL | let _ = val % 2;
|
||||
| +++++++
|
||||
|
||||
warning: unused logical operation that must be used
|
||||
--> $DIR/must-use-ops.rs:27:5
|
||||
--> $DIR/must-use-ops.rs:33:5
|
||||
|
|
||||
LL | true && true;
|
||||
| ^^^^^^^^^^^^ the logical operation produces a value
|
||||
@ -136,7 +136,7 @@ LL | let _ = true && true;
|
||||
| +++++++
|
||||
|
||||
warning: unused logical operation that must be used
|
||||
--> $DIR/must-use-ops.rs:28:5
|
||||
--> $DIR/must-use-ops.rs:34:5
|
||||
|
|
||||
LL | false || true;
|
||||
| ^^^^^^^^^^^^^ the logical operation produces a value
|
||||
@ -147,7 +147,7 @@ LL | let _ = false || true;
|
||||
| +++++++
|
||||
|
||||
warning: unused bitwise operation that must be used
|
||||
--> $DIR/must-use-ops.rs:31:5
|
||||
--> $DIR/must-use-ops.rs:37:5
|
||||
|
|
||||
LL | 5 ^ val;
|
||||
| ^^^^^^^ the bitwise operation produces a value
|
||||
@ -158,7 +158,7 @@ LL | let _ = 5 ^ val;
|
||||
| +++++++
|
||||
|
||||
warning: unused bitwise operation that must be used
|
||||
--> $DIR/must-use-ops.rs:32:5
|
||||
--> $DIR/must-use-ops.rs:38:5
|
||||
|
|
||||
LL | 5 & val;
|
||||
| ^^^^^^^ the bitwise operation produces a value
|
||||
@ -169,7 +169,7 @@ LL | let _ = 5 & val;
|
||||
| +++++++
|
||||
|
||||
warning: unused bitwise operation that must be used
|
||||
--> $DIR/must-use-ops.rs:33:5
|
||||
--> $DIR/must-use-ops.rs:39:5
|
||||
|
|
||||
LL | 5 | val;
|
||||
| ^^^^^^^ the bitwise operation produces a value
|
||||
@ -180,7 +180,7 @@ LL | let _ = 5 | val;
|
||||
| +++++++
|
||||
|
||||
warning: unused bitwise operation that must be used
|
||||
--> $DIR/must-use-ops.rs:34:5
|
||||
--> $DIR/must-use-ops.rs:40:5
|
||||
|
|
||||
LL | 5 << val;
|
||||
| ^^^^^^^^ the bitwise operation produces a value
|
||||
@ -191,7 +191,7 @@ LL | let _ = 5 << val;
|
||||
| +++++++
|
||||
|
||||
warning: unused bitwise operation that must be used
|
||||
--> $DIR/must-use-ops.rs:35:5
|
||||
--> $DIR/must-use-ops.rs:41:5
|
||||
|
|
||||
LL | 5 >> val;
|
||||
| ^^^^^^^^ the bitwise operation produces a value
|
||||
@ -202,7 +202,7 @@ LL | let _ = 5 >> val;
|
||||
| +++++++
|
||||
|
||||
warning: unused unary operation that must be used
|
||||
--> $DIR/must-use-ops.rs:38:5
|
||||
--> $DIR/must-use-ops.rs:44:5
|
||||
|
|
||||
LL | !val;
|
||||
| ^^^^ the unary operation produces a value
|
||||
@ -213,7 +213,7 @@ LL | let _ = !val;
|
||||
| +++++++
|
||||
|
||||
warning: unused unary operation that must be used
|
||||
--> $DIR/must-use-ops.rs:39:5
|
||||
--> $DIR/must-use-ops.rs:45:5
|
||||
|
|
||||
LL | -val;
|
||||
| ^^^^ the unary operation produces a value
|
||||
@ -224,7 +224,7 @@ LL | let _ = -val;
|
||||
| +++++++
|
||||
|
||||
warning: unused unary operation that must be used
|
||||
--> $DIR/must-use-ops.rs:40:5
|
||||
--> $DIR/must-use-ops.rs:46:5
|
||||
|
|
||||
LL | *val_pointer;
|
||||
| ^^^^^^^^^^^^ the unary operation produces a value
|
||||
|
@ -1,6 +1,7 @@
|
||||
#![deny(unused_must_use)]
|
||||
|
||||
#[must_use]
|
||||
#[derive(Clone, Copy)]
|
||||
struct S;
|
||||
|
||||
struct A;
|
||||
@ -34,6 +35,10 @@ fn array_of_arrays_of_arrays() -> [[[S; 1]; 2]; 1] {
|
||||
[[[S], [S]]]
|
||||
}
|
||||
|
||||
fn usize_max() -> [S; usize::MAX] {
|
||||
[S; usize::MAX]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
empty(); // ok
|
||||
singleton(); //~ ERROR unused array of `S` that must be used
|
||||
@ -44,4 +49,6 @@ fn main() {
|
||||
//~^ 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
|
||||
usize_max();
|
||||
//~^ ERROR unused array of `S` that must be used
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: unused array of `S` that must be used
|
||||
--> $DIR/must_use-array.rs:39:5
|
||||
--> $DIR/must_use-array.rs:44:5
|
||||
|
|
||||
LL | singleton();
|
||||
| ^^^^^^^^^^^
|
||||
@ -11,34 +11,40 @@ LL | #![deny(unused_must_use)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused array of `S` that must be used
|
||||
--> $DIR/must_use-array.rs:40:5
|
||||
--> $DIR/must_use-array.rs:45:5
|
||||
|
|
||||
LL | many();
|
||||
| ^^^^^^
|
||||
|
||||
error: unused array of `S` in tuple element 0 that must be used
|
||||
--> $DIR/must_use-array.rs:41:6
|
||||
--> $DIR/must_use-array.rs:46:6
|
||||
|
|
||||
LL | ([S], 0, ());
|
||||
| ^^^
|
||||
|
||||
error: unused array of implementers of `T` that must be used
|
||||
--> $DIR/must_use-array.rs:42:5
|
||||
--> $DIR/must_use-array.rs:47: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
|
||||
--> $DIR/must_use-array.rs:48:5
|
||||
|
|
||||
LL | impl_array();
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: unused array of arrays of arrays of `S` that must be used
|
||||
--> $DIR/must_use-array.rs:45:5
|
||||
--> $DIR/must_use-array.rs:50:5
|
||||
|
|
||||
LL | array_of_arrays_of_arrays();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: unused array of `S` that must be used
|
||||
--> $DIR/must_use-array.rs:52:5
|
||||
|
|
||||
LL | usize_max();
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user