Auto merge of #50149 - aaronaaeng:master, r=estebank
Added warning for unused arithmetic expressions The compiler now displays a warning when a binary arithmetic operation is evaluated but not used. This resolves #50124 by following the instructions outlined in the issue. The changes are as follows: - Added new pattern matching for unused arithmetic expressions in `src/librustc_lint/unused.rs` - Added `#[must_use]` attributes to the binary operation methods in `src/libcore/internal_macros.rs` - Added `#[must_use]` attributes to the non-assigning binary operators in `src/libcore/ops/arith.rs`
This commit is contained in:
commit
1eb0cef62b
6 changed files with 224 additions and 15 deletions
|
@ -94,6 +94,7 @@ pub trait Add<RHS=Self> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the `+` operation.
|
/// Performs the `+` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn add(self, rhs: RHS) -> Self::Output;
|
fn add(self, rhs: RHS) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
@ -191,6 +192,7 @@ pub trait Sub<RHS=Self> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the `-` operation.
|
/// Performs the `-` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn sub(self, rhs: RHS) -> Self::Output;
|
fn sub(self, rhs: RHS) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
@ -310,6 +312,7 @@ pub trait Mul<RHS=Self> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the `*` operation.
|
/// Performs the `*` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn mul(self, rhs: RHS) -> Self::Output;
|
fn mul(self, rhs: RHS) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
@ -433,6 +436,7 @@ pub trait Div<RHS=Self> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the `/` operation.
|
/// Performs the `/` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn div(self, rhs: RHS) -> Self::Output;
|
fn div(self, rhs: RHS) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
@ -517,6 +521,7 @@ pub trait Rem<RHS=Self> {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
/// Performs the `%` operation.
|
/// Performs the `%` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn rem(self, rhs: RHS) -> Self::Output;
|
fn rem(self, rhs: RHS) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
@ -601,6 +606,7 @@ pub trait Neg {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the unary `-` operation.
|
/// Performs the unary `-` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn neg(self) -> Self::Output;
|
fn neg(self) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ pub trait Not {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the unary `!` operation.
|
/// Performs the unary `!` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn not(self) -> Self::Output;
|
fn not(self) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
@ -129,6 +130,7 @@ pub trait BitAnd<RHS=Self> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the `&` operation.
|
/// Performs the `&` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn bitand(self, rhs: RHS) -> Self::Output;
|
fn bitand(self, rhs: RHS) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
@ -212,6 +214,7 @@ pub trait BitOr<RHS=Self> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the `|` operation.
|
/// Performs the `|` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn bitor(self, rhs: RHS) -> Self::Output;
|
fn bitor(self, rhs: RHS) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
@ -298,6 +301,7 @@ pub trait BitXor<RHS=Self> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the `^` operation.
|
/// Performs the `^` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn bitxor(self, rhs: RHS) -> Self::Output;
|
fn bitxor(self, rhs: RHS) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
@ -385,6 +389,7 @@ pub trait Shl<RHS=Self> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the `<<` operation.
|
/// Performs the `<<` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn shl(self, rhs: RHS) -> Self::Output;
|
fn shl(self, rhs: RHS) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
@ -493,6 +498,7 @@ pub trait Shr<RHS=Self> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Performs the `>>` operation.
|
/// Performs the `>>` operation.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn shr(self, rhs: RHS) -> Self::Output;
|
fn shr(self, rhs: RHS) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,7 @@ pub trait Deref {
|
||||||
type Target: ?Sized;
|
type Target: ?Sized;
|
||||||
|
|
||||||
/// Dereferences the value.
|
/// Dereferences the value.
|
||||||
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn deref(&self) -> &Self::Target;
|
fn deref(&self) -> &Self::Target;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,23 +91,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
|
||||||
let def_id = def.def_id();
|
let def_id = def.def_id();
|
||||||
fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
|
fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
|
||||||
}
|
}
|
||||||
|
let must_use_op = match expr.node {
|
||||||
if let hir::ExprBinary(bin_op, ..) = expr.node {
|
// Hardcoding operators here seemed more expedient than the
|
||||||
|
// refactoring that would be needed to look up the `#[must_use]`
|
||||||
|
// attribute which does exist on the comparison trait methods
|
||||||
|
hir::ExprBinary(bin_op, ..) => {
|
||||||
match bin_op.node {
|
match bin_op.node {
|
||||||
// Hardcoding the comparison operators here seemed more
|
|
||||||
// expedient than the refactoring that would be needed to
|
|
||||||
// look up the `#[must_use]` attribute which does exist on
|
|
||||||
// the comparison trait methods
|
|
||||||
hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => {
|
hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => {
|
||||||
let msg = "unused comparison which must be used";
|
Some("comparison")
|
||||||
cx.span_lint(UNUSED_MUST_USE, expr.span, msg);
|
|
||||||
op_warned = true;
|
|
||||||
},
|
},
|
||||||
_ => {},
|
hir::BiAdd | hir::BiSub | hir::BiDiv | hir::BiMul | hir::BiRem => {
|
||||||
|
Some("arithmetic operation")
|
||||||
|
},
|
||||||
|
hir::BiAnd | hir::BiOr => {
|
||||||
|
Some("logical operation")
|
||||||
|
},
|
||||||
|
hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr | hir::BiShl | hir::BiShr => {
|
||||||
|
Some("bitwise operation")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hir::ExprUnary(..) => Some("unary operation"),
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
if let Some(must_use_op) = must_use_op {
|
||||||
|
cx.span_lint(UNUSED_MUST_USE, expr.span,
|
||||||
|
&format!("unused {} which must be used", must_use_op));
|
||||||
|
op_warned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !(ty_warned || fn_warned || op_warned) {
|
if !(ty_warned || fn_warned || op_warned) {
|
||||||
cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
|
cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
|
||||||
}
|
}
|
||||||
|
|
52
src/test/ui/lint/must-use-ops.rs
Normal file
52
src/test/ui/lint/must-use-ops.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Issue #50124 - Test warning for unused operator expressions
|
||||||
|
|
||||||
|
// compile-pass
|
||||||
|
|
||||||
|
#![feature(fn_must_use)]
|
||||||
|
#![warn(unused_must_use)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let val = 1;
|
||||||
|
let val_pointer = &val;
|
||||||
|
|
||||||
|
// Comparison Operators
|
||||||
|
val == 1;
|
||||||
|
val < 1;
|
||||||
|
val <= 1;
|
||||||
|
val != 1;
|
||||||
|
val >= 1;
|
||||||
|
val > 1;
|
||||||
|
|
||||||
|
// Arithmetic Operators
|
||||||
|
val + 2;
|
||||||
|
val - 2;
|
||||||
|
val / 2;
|
||||||
|
val * 2;
|
||||||
|
val % 2;
|
||||||
|
|
||||||
|
// Logical Operators
|
||||||
|
true && true;
|
||||||
|
false || true;
|
||||||
|
|
||||||
|
// Bitwise Operators
|
||||||
|
5 ^ val;
|
||||||
|
5 & val;
|
||||||
|
5 | val;
|
||||||
|
5 << val;
|
||||||
|
5 >> val;
|
||||||
|
|
||||||
|
// Unary Operators
|
||||||
|
!val;
|
||||||
|
-val;
|
||||||
|
*val_pointer;
|
||||||
|
}
|
132
src/test/ui/lint/must-use-ops.stderr
Normal file
132
src/test/ui/lint/must-use-ops.stderr
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
warning: unused comparison which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:23:5
|
||||||
|
|
|
||||||
|
LL | val == 1;
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
note: lint level defined here
|
||||||
|
--> $DIR/must-use-ops.rs:16:9
|
||||||
|
|
|
||||||
|
LL | #![warn(unused_must_use)]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused comparison which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:24:5
|
||||||
|
|
|
||||||
|
LL | val < 1;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused comparison which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:25:5
|
||||||
|
|
|
||||||
|
LL | val <= 1;
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused comparison which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:26:5
|
||||||
|
|
|
||||||
|
LL | val != 1;
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused comparison which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:27:5
|
||||||
|
|
|
||||||
|
LL | val >= 1;
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused comparison which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:28:5
|
||||||
|
|
|
||||||
|
LL | val > 1;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused arithmetic operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:31:5
|
||||||
|
|
|
||||||
|
LL | val + 2;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused arithmetic operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:32:5
|
||||||
|
|
|
||||||
|
LL | val - 2;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused arithmetic operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:33:5
|
||||||
|
|
|
||||||
|
LL | val / 2;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused arithmetic operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:34:5
|
||||||
|
|
|
||||||
|
LL | val * 2;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused arithmetic operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:35:5
|
||||||
|
|
|
||||||
|
LL | val % 2;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused logical operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:38:5
|
||||||
|
|
|
||||||
|
LL | true && true;
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused logical operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:39:5
|
||||||
|
|
|
||||||
|
LL | false || true;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused bitwise operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:42:5
|
||||||
|
|
|
||||||
|
LL | 5 ^ val;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused bitwise operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:43:5
|
||||||
|
|
|
||||||
|
LL | 5 & val;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused bitwise operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:44:5
|
||||||
|
|
|
||||||
|
LL | 5 | val;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
warning: unused bitwise operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:45:5
|
||||||
|
|
|
||||||
|
LL | 5 << val;
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused bitwise operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:46:5
|
||||||
|
|
|
||||||
|
LL | 5 >> val;
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
warning: unused unary operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:49:5
|
||||||
|
|
|
||||||
|
LL | !val;
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
warning: unused unary operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:50:5
|
||||||
|
|
|
||||||
|
LL | -val;
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
warning: unused unary operation which must be used
|
||||||
|
--> $DIR/must-use-ops.rs:51:5
|
||||||
|
|
|
||||||
|
LL | *val_pointer;
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue