538 lines
12 KiB
Rust
538 lines
12 KiB
Rust
//@aux-build:proc_macro_derive.rs
|
|
|
|
#![feature(f128)]
|
|
#![feature(f16)]
|
|
#![allow(
|
|
clippy::assign_op_pattern,
|
|
clippy::erasing_op,
|
|
clippy::identity_op,
|
|
clippy::no_effect,
|
|
clippy::op_ref,
|
|
clippy::unnecessary_owned_empty_strings,
|
|
arithmetic_overflow,
|
|
unconditional_panic
|
|
)]
|
|
#![warn(clippy::arithmetic_side_effects)]
|
|
|
|
extern crate proc_macro_derive;
|
|
|
|
use core::num::{NonZero, Saturating, Wrapping};
|
|
|
|
const ONE: i32 = 1;
|
|
const ZERO: i32 = 0;
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct Custom;
|
|
|
|
#[derive(proc_macro_derive::ShadowDerive)]
|
|
pub struct Nothing;
|
|
|
|
macro_rules! impl_arith {
|
|
( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
|
|
$(
|
|
impl core::ops::$_trait<$lhs> for $rhs {
|
|
type Output = Custom;
|
|
fn $method(self, _: $lhs) -> Self::Output { todo!() }
|
|
}
|
|
)*
|
|
}
|
|
}
|
|
|
|
macro_rules! impl_assign_arith {
|
|
( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
|
|
$(
|
|
impl core::ops::$_trait<$lhs> for $rhs {
|
|
fn $method(&mut self, _: $lhs) {}
|
|
}
|
|
)*
|
|
}
|
|
}
|
|
|
|
impl_arith!(
|
|
Add, Custom, Custom, add;
|
|
Div, Custom, Custom, div;
|
|
Mul, Custom, Custom, mul;
|
|
Rem, Custom, Custom, rem;
|
|
Shl, Custom, Custom, shl;
|
|
Shr, Custom, Custom, shr;
|
|
Sub, Custom, Custom, sub;
|
|
|
|
Add, Custom, &Custom, add;
|
|
Div, Custom, &Custom, div;
|
|
Mul, Custom, &Custom, mul;
|
|
Rem, Custom, &Custom, rem;
|
|
Shl, Custom, &Custom, shl;
|
|
Shr, Custom, &Custom, shr;
|
|
Sub, Custom, &Custom, sub;
|
|
|
|
Add, &Custom, Custom, add;
|
|
Div, &Custom, Custom, div;
|
|
Mul, &Custom, Custom, mul;
|
|
Rem, &Custom, Custom, rem;
|
|
Shl, &Custom, Custom, shl;
|
|
Shr, &Custom, Custom, shr;
|
|
Sub, &Custom, Custom, sub;
|
|
|
|
Add, &Custom, &Custom, add;
|
|
Div, &Custom, &Custom, div;
|
|
Mul, &Custom, &Custom, mul;
|
|
Rem, &Custom, &Custom, rem;
|
|
Shl, &Custom, &Custom, shl;
|
|
Shr, &Custom, &Custom, shr;
|
|
Sub, &Custom, &Custom, sub;
|
|
);
|
|
|
|
impl_assign_arith!(
|
|
AddAssign, Custom, Custom, add_assign;
|
|
DivAssign, Custom, Custom, div_assign;
|
|
MulAssign, Custom, Custom, mul_assign;
|
|
RemAssign, Custom, Custom, rem_assign;
|
|
ShlAssign, Custom, Custom, shl_assign;
|
|
ShrAssign, Custom, Custom, shr_assign;
|
|
SubAssign, Custom, Custom, sub_assign;
|
|
|
|
AddAssign, Custom, &Custom, add_assign;
|
|
DivAssign, Custom, &Custom, div_assign;
|
|
MulAssign, Custom, &Custom, mul_assign;
|
|
RemAssign, Custom, &Custom, rem_assign;
|
|
ShlAssign, Custom, &Custom, shl_assign;
|
|
ShrAssign, Custom, &Custom, shr_assign;
|
|
SubAssign, Custom, &Custom, sub_assign;
|
|
|
|
AddAssign, &Custom, Custom, add_assign;
|
|
DivAssign, &Custom, Custom, div_assign;
|
|
MulAssign, &Custom, Custom, mul_assign;
|
|
RemAssign, &Custom, Custom, rem_assign;
|
|
ShlAssign, &Custom, Custom, shl_assign;
|
|
ShrAssign, &Custom, Custom, shr_assign;
|
|
SubAssign, &Custom, Custom, sub_assign;
|
|
|
|
AddAssign, &Custom, &Custom, add_assign;
|
|
DivAssign, &Custom, &Custom, div_assign;
|
|
MulAssign, &Custom, &Custom, mul_assign;
|
|
RemAssign, &Custom, &Custom, rem_assign;
|
|
ShlAssign, &Custom, &Custom, shl_assign;
|
|
ShrAssign, &Custom, &Custom, shr_assign;
|
|
SubAssign, &Custom, &Custom, sub_assign;
|
|
);
|
|
|
|
impl core::ops::Neg for Custom {
|
|
type Output = Custom;
|
|
fn neg(self) -> Self::Output {
|
|
todo!()
|
|
}
|
|
}
|
|
impl core::ops::Neg for &Custom {
|
|
type Output = Custom;
|
|
fn neg(self) -> Self::Output {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
pub fn association_with_structures_should_not_trigger_the_lint() {
|
|
enum Foo {
|
|
Bar = -2,
|
|
}
|
|
|
|
impl Trait for Foo {
|
|
const ASSOC: i32 = {
|
|
let _: [i32; 1 + 1];
|
|
fn foo() {}
|
|
1 + 1
|
|
};
|
|
}
|
|
|
|
struct Baz([i32; 1 + 1]);
|
|
|
|
trait Trait {
|
|
const ASSOC: i32 = 1 + 1;
|
|
}
|
|
|
|
type Alias = [i32; 1 + 1];
|
|
|
|
union Qux {
|
|
field: [i32; 1 + 1],
|
|
}
|
|
|
|
let _: [i32; 1 + 1] = [0, 0];
|
|
|
|
let _: [i32; 1 + 1] = {
|
|
let a: [i32; 1 + 1] = [0, 0];
|
|
a
|
|
};
|
|
}
|
|
|
|
pub fn hard_coded_allowed() {
|
|
let _ = 1f16 + 1f16;
|
|
let _ = 1f32 + 1f32;
|
|
let _ = 1f64 + 1f64;
|
|
let _ = 1f128 + 1f128;
|
|
|
|
let _ = Saturating(0u32) + Saturating(0u32);
|
|
let _ = String::new() + "";
|
|
let _ = Wrapping(0u32) + Wrapping(0u32);
|
|
|
|
let saturating: Saturating<u32> = Saturating(0u32);
|
|
let string: String = String::new();
|
|
let wrapping: Wrapping<u32> = Wrapping(0u32);
|
|
|
|
let inferred_saturating = saturating + saturating;
|
|
let inferred_string = string + "";
|
|
let inferred_wrapping = wrapping + wrapping;
|
|
|
|
let _ = inferred_saturating + inferred_saturating;
|
|
let _ = inferred_string + "";
|
|
let _ = inferred_wrapping + inferred_wrapping;
|
|
}
|
|
|
|
#[rustfmt::skip]
|
|
pub fn const_ops_should_not_trigger_the_lint() {
|
|
const _: i32 = { let mut n = 1; n += 1; n };
|
|
let _ = const { let mut n = 1; n += 1; n };
|
|
|
|
const _: i32 = { let mut n = 1; n = n + 1; n };
|
|
let _ = const { let mut n = 1; n = n + 1; n };
|
|
|
|
const _: i32 = { let mut n = 1; n = 1 + n; n };
|
|
let _ = const { let mut n = 1; n = 1 + n; n };
|
|
|
|
const _: i32 = 1 + 1;
|
|
let _ = const { 1 + 1 };
|
|
|
|
const _: i32 = { let mut n = 1; n = -1; n = -(-1); n = -n; n };
|
|
let _ = const { let mut n = 1; n = -1; n = -(-1); n = -n; n };
|
|
}
|
|
|
|
pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_trigger_the_lint() {
|
|
let mut _n = i32::MAX;
|
|
|
|
// Assign
|
|
_n += 0;
|
|
_n += &0;
|
|
_n -= 0;
|
|
_n -= &0;
|
|
_n += ZERO;
|
|
_n += &ZERO;
|
|
_n -= ZERO;
|
|
_n -= &ZERO;
|
|
_n /= 99;
|
|
_n /= &99;
|
|
_n %= 99;
|
|
_n %= &99;
|
|
_n *= 0;
|
|
_n *= &0;
|
|
_n *= 1;
|
|
_n *= &1;
|
|
_n *= ZERO;
|
|
_n *= &ZERO;
|
|
_n *= ONE;
|
|
_n *= &ONE;
|
|
_n += -0;
|
|
_n += &-0;
|
|
_n -= -0;
|
|
_n -= &-0;
|
|
_n += -ZERO;
|
|
_n += &-ZERO;
|
|
_n -= -ZERO;
|
|
_n -= &-ZERO;
|
|
_n /= -99;
|
|
_n /= &-99;
|
|
_n %= -99;
|
|
_n %= &-99;
|
|
_n *= -0;
|
|
_n *= &-0;
|
|
_n *= -1;
|
|
_n *= &-1;
|
|
|
|
// Binary
|
|
_n = _n + 0;
|
|
_n = _n + &0;
|
|
_n = 0 + _n;
|
|
_n = &0 + _n;
|
|
_n = _n + ZERO;
|
|
_n = _n + &ZERO;
|
|
_n = ZERO + _n;
|
|
_n = &ZERO + _n;
|
|
_n = _n - 0;
|
|
_n = _n - &0;
|
|
_n = 0 - _n;
|
|
_n = &0 - _n;
|
|
_n = _n - ZERO;
|
|
_n = _n - &ZERO;
|
|
_n = ZERO - _n;
|
|
_n = &ZERO - _n;
|
|
_n = _n / 99;
|
|
_n = _n / &99;
|
|
_n = _n % 99;
|
|
_n = _n % &99;
|
|
_n = _n * 0;
|
|
_n = _n * &0;
|
|
_n = 0 * _n;
|
|
_n = &0 * _n;
|
|
_n = _n * 1;
|
|
_n = _n * &1;
|
|
_n = ZERO * _n;
|
|
_n = &ZERO * _n;
|
|
_n = _n * ONE;
|
|
_n = _n * &ONE;
|
|
_n = 1 * _n;
|
|
_n = &1 * _n;
|
|
_n = 23 + 85;
|
|
|
|
// Method
|
|
_n.saturating_div(1);
|
|
_n.wrapping_div(1);
|
|
_n.wrapping_rem(1);
|
|
_n.wrapping_rem_euclid(1);
|
|
|
|
_n.saturating_div(1);
|
|
_n.checked_div(1);
|
|
_n.checked_rem(1);
|
|
_n.checked_rem_euclid(1);
|
|
|
|
// Unary
|
|
_n = -2147483647;
|
|
_n = -i32::MAX;
|
|
_n = -i32::MIN;
|
|
_n = -&2147483647;
|
|
_n = -&i32::MAX;
|
|
_n = -&i32::MIN;
|
|
}
|
|
|
|
pub fn unknown_ops_or_runtime_ops_that_can_overflow() {
|
|
let mut _n = i32::MAX;
|
|
let mut _custom = Custom;
|
|
|
|
// Assign
|
|
_n += 1;
|
|
_n += &1;
|
|
_n -= 1;
|
|
_n -= &1;
|
|
_n /= 0;
|
|
_n /= &0;
|
|
_n %= 0;
|
|
_n %= &0;
|
|
_n *= 2;
|
|
_n *= &2;
|
|
_n += -1;
|
|
_n += &-1;
|
|
_n -= -1;
|
|
_n -= &-1;
|
|
_n /= -0;
|
|
_n /= &-0;
|
|
_n %= -0;
|
|
_n %= &-0;
|
|
_n *= -2;
|
|
_n *= &-2;
|
|
_custom += Custom;
|
|
_custom += &Custom;
|
|
_custom -= Custom;
|
|
_custom -= &Custom;
|
|
_custom /= Custom;
|
|
_custom /= &Custom;
|
|
_custom %= Custom;
|
|
_custom %= &Custom;
|
|
_custom *= Custom;
|
|
_custom *= &Custom;
|
|
_custom >>= Custom;
|
|
_custom >>= &Custom;
|
|
_custom <<= Custom;
|
|
_custom <<= &Custom;
|
|
_custom += -Custom;
|
|
_custom += &-Custom;
|
|
_custom -= -Custom;
|
|
_custom -= &-Custom;
|
|
_custom /= -Custom;
|
|
_custom /= &-Custom;
|
|
_custom %= -Custom;
|
|
_custom %= &-Custom;
|
|
_custom *= -Custom;
|
|
_custom *= &-Custom;
|
|
_custom >>= -Custom;
|
|
_custom >>= &-Custom;
|
|
_custom <<= -Custom;
|
|
_custom <<= &-Custom;
|
|
|
|
// Binary
|
|
_n = _n + 1;
|
|
_n = _n + &1;
|
|
_n = 1 + _n;
|
|
_n = &1 + _n;
|
|
_n = _n - 1;
|
|
_n = _n - &1;
|
|
_n = 1 - _n;
|
|
_n = &1 - _n;
|
|
_n = _n / 0;
|
|
_n = _n / &0;
|
|
_n = _n % 0;
|
|
_n = _n % &0;
|
|
_n = _n * 2;
|
|
_n = _n * &2;
|
|
_n = 2 * _n;
|
|
_n = &2 * _n;
|
|
_n = 23 + &85;
|
|
_n = &23 + 85;
|
|
_n = &23 + &85;
|
|
_custom = _custom + _custom;
|
|
_custom = _custom + &_custom;
|
|
_custom = Custom + _custom;
|
|
_custom = &Custom + _custom;
|
|
_custom = _custom - Custom;
|
|
_custom = _custom - &Custom;
|
|
_custom = Custom - _custom;
|
|
_custom = &Custom - _custom;
|
|
_custom = _custom / Custom;
|
|
_custom = _custom / &Custom;
|
|
_custom = _custom % Custom;
|
|
_custom = _custom % &Custom;
|
|
_custom = _custom * Custom;
|
|
_custom = _custom * &Custom;
|
|
_custom = Custom * _custom;
|
|
_custom = &Custom * _custom;
|
|
_custom = Custom + &Custom;
|
|
_custom = &Custom + Custom;
|
|
_custom = &Custom + &Custom;
|
|
_custom = _custom >> _custom;
|
|
_custom = _custom >> &_custom;
|
|
_custom = Custom << _custom;
|
|
_custom = &Custom << _custom;
|
|
|
|
// Method
|
|
_n.saturating_div(0);
|
|
_n.wrapping_div(0);
|
|
_n.wrapping_rem(0);
|
|
_n.wrapping_rem_euclid(0);
|
|
|
|
_n.saturating_div(_n);
|
|
_n.wrapping_div(_n);
|
|
_n.wrapping_rem(_n);
|
|
_n.wrapping_rem_euclid(_n);
|
|
|
|
// Unary
|
|
_n = -_n;
|
|
_n = -&_n;
|
|
_custom = -_custom;
|
|
_custom = -&_custom;
|
|
}
|
|
|
|
// Copied and pasted from the `integer_arithmetic` lint for comparison.
|
|
pub fn integer_arithmetic() {
|
|
let mut i = 1i32;
|
|
let mut var1 = 0i32;
|
|
let mut var2 = -1i32;
|
|
|
|
1 + i;
|
|
i * 2;
|
|
1 % i / 2;
|
|
i - 2 + 2 - i;
|
|
-i;
|
|
i >> 1;
|
|
i << 1;
|
|
|
|
-1;
|
|
-(-1);
|
|
|
|
i & 1;
|
|
i | 1;
|
|
i ^ 1;
|
|
|
|
i += 1;
|
|
i -= 1;
|
|
i *= 2;
|
|
i /= 2;
|
|
i /= 0;
|
|
i /= -1;
|
|
i /= var1;
|
|
i /= var2;
|
|
i %= 2;
|
|
i %= 0;
|
|
i %= -1;
|
|
i %= var1;
|
|
i %= var2;
|
|
i <<= 3;
|
|
i >>= 2;
|
|
|
|
i |= 1;
|
|
i &= 1;
|
|
i ^= i;
|
|
}
|
|
|
|
pub fn issue_10583(a: u16) -> u16 {
|
|
10 / a
|
|
}
|
|
|
|
pub fn issue_10767() {
|
|
let n = &1.0;
|
|
n + n;
|
|
3.1_f32 + &1.2_f32;
|
|
&3.4_f32 + 1.5_f32;
|
|
&3.5_f32 + &1.3_f32;
|
|
}
|
|
|
|
pub fn issue_10792() {
|
|
struct One {
|
|
a: u32,
|
|
}
|
|
struct Two {
|
|
b: u32,
|
|
c: u64,
|
|
}
|
|
const ONE: One = One { a: 1 };
|
|
const TWO: Two = Two { b: 2, c: 3 };
|
|
let _ = 10 / ONE.a;
|
|
let _ = 10 / TWO.b;
|
|
let _ = 10 / TWO.c;
|
|
}
|
|
|
|
pub fn issue_11145() {
|
|
let mut x: Wrapping<u32> = Wrapping(0_u32);
|
|
x += 1;
|
|
}
|
|
|
|
pub fn issue_11262() {
|
|
let one = 1;
|
|
let zero = 0;
|
|
let _ = 2 / one;
|
|
let _ = 2 / zero;
|
|
}
|
|
|
|
pub fn issue_11392() {
|
|
fn example_div(unsigned: usize, nonzero_unsigned: NonZero<usize>) -> usize {
|
|
unsigned / nonzero_unsigned
|
|
}
|
|
|
|
fn example_rem(unsigned: usize, nonzero_unsigned: NonZero<usize>) -> usize {
|
|
unsigned % nonzero_unsigned
|
|
}
|
|
|
|
let (unsigned, nonzero_unsigned) = (0, NonZero::new(1).unwrap());
|
|
example_div(unsigned, nonzero_unsigned);
|
|
example_rem(unsigned, nonzero_unsigned);
|
|
}
|
|
|
|
pub fn issue_11393() {
|
|
fn example_div(x: Wrapping<i32>, maybe_zero: Wrapping<i32>) -> Wrapping<i32> {
|
|
x / maybe_zero
|
|
}
|
|
|
|
fn example_rem(x: Wrapping<i32>, maybe_zero: Wrapping<i32>) -> Wrapping<i32> {
|
|
x % maybe_zero
|
|
}
|
|
|
|
let [x, maybe_zero] = [1, 0].map(Wrapping);
|
|
example_div(x, maybe_zero);
|
|
example_rem(x, maybe_zero);
|
|
}
|
|
|
|
pub fn issue_12318() {
|
|
use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
|
|
let mut one: i32 = 1;
|
|
one.add_assign(1);
|
|
one.div_assign(1);
|
|
one.mul_assign(1);
|
|
one.rem_assign(1);
|
|
one.sub_assign(1);
|
|
}
|
|
|
|
fn main() {}
|