fix: assign_op_pattern FP on unstable const trait
This commit is contained in:
parent
1029572c19
commit
03af37302c
6 changed files with 90 additions and 15 deletions
|
|
@ -1,8 +1,10 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::msrvs::Msrv;
|
||||
use clippy_utils::qualify_min_const_fn::is_stable_const_fn;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use clippy_utils::visitors::for_each_expr_without_closures;
|
||||
use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method};
|
||||
use clippy_utils::{binop_traits, eq_expr_value, is_in_const_context, trait_ref_of_method};
|
||||
use core::ops::ControlFlow;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
|
|
@ -19,6 +21,7 @@ pub(super) fn check<'tcx>(
|
|||
expr: &'tcx hir::Expr<'_>,
|
||||
assignee: &'tcx hir::Expr<'_>,
|
||||
e: &'tcx hir::Expr<'_>,
|
||||
msrv: Msrv,
|
||||
) {
|
||||
if let hir::ExprKind::Binary(op, l, r) = &e.kind {
|
||||
let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| {
|
||||
|
|
@ -40,6 +43,15 @@ pub(super) fn check<'tcx>(
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip if the trait is not stable in const contexts
|
||||
if is_in_const_context(cx)
|
||||
&& let Some(binop_id) = cx.tcx.associated_item_def_ids(trait_id).first()
|
||||
&& !is_stable_const_fn(cx, *binop_id, msrv)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
ASSIGN_OP_PATTERN,
|
||||
|
|
|
|||
|
|
@ -919,7 +919,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
|
|||
modulo_arithmetic::check(cx, e, bin_op, lhs, rhs, false);
|
||||
},
|
||||
ExprKind::Assign(lhs, rhs, _) => {
|
||||
assign_op_pattern::check(cx, e, lhs, rhs);
|
||||
assign_op_pattern::check(cx, e, lhs, rhs, self.msrv);
|
||||
self_assignment::check(cx, e, lhs, rhs);
|
||||
},
|
||||
ExprKind::Unary(op, arg) => {
|
||||
|
|
|
|||
|
|
@ -393,7 +393,8 @@ fn check_terminator<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bool {
|
||||
/// Checks if the given `def_id` is a stable const fn, in respect to the given MSRV.
|
||||
pub fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bool {
|
||||
cx.tcx.is_const_fn(def_id)
|
||||
&& cx
|
||||
.tcx
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(clippy::useless_vec)]
|
||||
#![warn(clippy::assign_op_pattern)]
|
||||
#![feature(const_trait_impl, const_ops)]
|
||||
|
||||
use core::num::Wrapping;
|
||||
use std::ops::{Mul, MulAssign};
|
||||
|
|
@ -73,3 +74,33 @@ impl MulAssign<i64> for Wrap {
|
|||
*self = *self * rhs
|
||||
}
|
||||
}
|
||||
|
||||
mod issue14871 {
|
||||
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
pub trait Number: Copy + Add<Self, Output = Self> + AddAssign {
|
||||
const ZERO: Self;
|
||||
const ONE: Self;
|
||||
}
|
||||
|
||||
#[const_trait]
|
||||
pub trait NumberConstants {
|
||||
fn constant(value: usize) -> Self;
|
||||
}
|
||||
|
||||
impl<T> const NumberConstants for T
|
||||
where
|
||||
T: Number + ~const core::ops::Add,
|
||||
{
|
||||
fn constant(value: usize) -> Self {
|
||||
let mut res = Self::ZERO;
|
||||
let mut count = 0;
|
||||
while count < value {
|
||||
res = res + Self::ONE;
|
||||
count += 1;
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(clippy::useless_vec)]
|
||||
#![warn(clippy::assign_op_pattern)]
|
||||
#![feature(const_trait_impl, const_ops)]
|
||||
|
||||
use core::num::Wrapping;
|
||||
use std::ops::{Mul, MulAssign};
|
||||
|
|
@ -73,3 +74,33 @@ impl MulAssign<i64> for Wrap {
|
|||
*self = *self * rhs
|
||||
}
|
||||
}
|
||||
|
||||
mod issue14871 {
|
||||
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
pub trait Number: Copy + Add<Self, Output = Self> + AddAssign {
|
||||
const ZERO: Self;
|
||||
const ONE: Self;
|
||||
}
|
||||
|
||||
#[const_trait]
|
||||
pub trait NumberConstants {
|
||||
fn constant(value: usize) -> Self;
|
||||
}
|
||||
|
||||
impl<T> const NumberConstants for T
|
||||
where
|
||||
T: Number + ~const core::ops::Add,
|
||||
{
|
||||
fn constant(value: usize) -> Self {
|
||||
let mut res = Self::ZERO;
|
||||
let mut count = 0;
|
||||
while count < value {
|
||||
res = res + Self::ONE;
|
||||
count += 1;
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:9:5
|
||||
--> tests/ui/assign_ops.rs:10:5
|
||||
|
|
||||
LL | a = a + 1;
|
||||
| ^^^^^^^^^ help: replace it with: `a += 1`
|
||||
|
|
@ -8,67 +8,67 @@ LL | a = a + 1;
|
|||
= help: to override `-D warnings` add `#[allow(clippy::assign_op_pattern)]`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:11:5
|
||||
--> tests/ui/assign_ops.rs:12:5
|
||||
|
|
||||
LL | a = 1 + a;
|
||||
| ^^^^^^^^^ help: replace it with: `a += 1`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:13:5
|
||||
--> tests/ui/assign_ops.rs:14:5
|
||||
|
|
||||
LL | a = a - 1;
|
||||
| ^^^^^^^^^ help: replace it with: `a -= 1`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:15:5
|
||||
--> tests/ui/assign_ops.rs:16:5
|
||||
|
|
||||
LL | a = a * 99;
|
||||
| ^^^^^^^^^^ help: replace it with: `a *= 99`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:17:5
|
||||
--> tests/ui/assign_ops.rs:18:5
|
||||
|
|
||||
LL | a = 42 * a;
|
||||
| ^^^^^^^^^^ help: replace it with: `a *= 42`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:19:5
|
||||
--> tests/ui/assign_ops.rs:20:5
|
||||
|
|
||||
LL | a = a / 2;
|
||||
| ^^^^^^^^^ help: replace it with: `a /= 2`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:21:5
|
||||
--> tests/ui/assign_ops.rs:22:5
|
||||
|
|
||||
LL | a = a % 5;
|
||||
| ^^^^^^^^^ help: replace it with: `a %= 5`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:23:5
|
||||
--> tests/ui/assign_ops.rs:24:5
|
||||
|
|
||||
LL | a = a & 1;
|
||||
| ^^^^^^^^^ help: replace it with: `a &= 1`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:30:5
|
||||
--> tests/ui/assign_ops.rs:31:5
|
||||
|
|
||||
LL | s = s + "bla";
|
||||
| ^^^^^^^^^^^^^ help: replace it with: `s += "bla"`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:35:5
|
||||
--> tests/ui/assign_ops.rs:36:5
|
||||
|
|
||||
LL | a = a + Wrapping(1u32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a += Wrapping(1u32)`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:38:5
|
||||
--> tests/ui/assign_ops.rs:39:5
|
||||
|
|
||||
LL | v[0] = v[0] + v[1];
|
||||
| ^^^^^^^^^^^^^^^^^^ help: replace it with: `v[0] += v[1]`
|
||||
|
||||
error: manual implementation of an assign operation
|
||||
--> tests/ui/assign_ops.rs:51:5
|
||||
--> tests/ui/assign_ops.rs:52:5
|
||||
|
|
||||
LL | buf = buf + cows.clone();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `buf += cows.clone()`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue