Skip to content

Commit a4f022e

Browse files
committed
Auto merge of rust-lang#78259 - plaflamme:fix-49660, r=KodrAus
Fix rust-lang#49660 - Adds checks to ensure existence of arithmetic trait implementations The first 2 commits fix an issue with the existing `wrapping.rs` tests. It wasn't referred to from the module, so the file was being ignored. This is fixed in rust-lang@872dc60 This surfaced a bug in its macro which is fixed in rust-lang@8ddad18 Lastly, commit rust-lang@64d695b is the actual tests for fixing rust-lang#49660 The following checks are done: * `Add`, `Sub`, `Mul`, `Div`, `Rem` * `T op T`, `T op &T`, `&T op T` and `&T op &T` * for all integer and floating point types * `AddAssign`, `SubAssign`, `MulAssign`, `DivAssign`, `RemAssign` * `&mut T op T` and `&mut T op &T` * for all integer and floating point types * `Neg` * `op T` and `op &T` * for all signed integer and floating point types * `Not` * `op T` and `op &T` * for `bool` * `BitAnd`, `BitOr`, `BitXor` * `T op T`, `T op &T`, `&T op T` and `&T op &T` * for all integer types and bool * `BitAndAssign`, `BitOrAssign`, `BitXorAssign` * `&mut T op T` and `&mut T op &T` * for all integer types and bool * `Shl`, `Shr` * `L op R`, `L op &R`, `&L op R` and `&L op &R` * for all pairs of integer types * `ShlAssign`, `ShrAssign` * `&mut L op R`, `&mut L op &R` * for all pairs of integer types NOTE: I'd like some feedback on improving the macros. I'm not familiar with the idioms and patterns there and composing them has been a challenge for me. [EDIT]: updated links to commits after rebase.
2 parents c7b0ddb + 64d695b commit a4f022e

File tree

3 files changed

+261
-14
lines changed

3 files changed

+261
-14
lines changed

library/core/tests/num/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ mod u8;
2929
mod bignum;
3030
mod dec2flt;
3131
mod flt2dec;
32+
mod ops;
33+
mod wrapping;
3234

3335
mod nan;
3436

library/core/tests/num/ops.rs

+244
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
use core::ops::*;
2+
3+
// For types L and R, checks that a trait implementation exists for
4+
// * binary ops: L op R, L op &R, &L op R and &L op &R
5+
// * assign ops: &mut L op R, &mut L op &R
6+
macro_rules! impl_defined {
7+
($op:ident, $method:ident($lhs:literal, $rhs:literal), $result:literal, $lt:ty, $rt:ty) => {
8+
let lhs = $lhs as $lt;
9+
let rhs = $rhs as $rt;
10+
assert_eq!($result as $lt, $op::$method(lhs, rhs));
11+
assert_eq!($result as $lt, $op::$method(lhs, &rhs));
12+
assert_eq!($result as $lt, $op::$method(&lhs, rhs));
13+
assert_eq!($result as $lt, $op::$method(&lhs, &rhs));
14+
};
15+
($op:ident, $method:ident(&mut $lhs:literal, $rhs:literal), $result:literal, $lt:ty, $rt:ty) => {
16+
let rhs = $rhs as $rt;
17+
let mut lhs = $lhs as $lt;
18+
$op::$method(&mut lhs, rhs);
19+
assert_eq!($result as $lt, lhs);
20+
21+
let mut lhs = $lhs as $lt;
22+
$op::$method(&mut lhs, &rhs);
23+
assert_eq!($result as $lt, lhs);
24+
};
25+
}
26+
27+
// For all specified types T, checks that a trait implementation exists for
28+
// * binary ops: T op T, T op &T, &T op T and &T op &T
29+
// * assign ops: &mut T op T, &mut T op &T
30+
// * unary ops: op T and op &T
31+
macro_rules! impls_defined {
32+
($op:ident, $method:ident($lhs:literal, $rhs:literal), $result:literal, $($t:ty),+) => {$(
33+
impl_defined!($op, $method($lhs, $rhs), $result, $t, $t);
34+
)+};
35+
($op:ident, $method:ident(&mut $lhs:literal, $rhs:literal), $result:literal, $($t:ty),+) => {$(
36+
impl_defined!($op, $method(&mut $lhs, $rhs), $result, $t, $t);
37+
)+};
38+
($op:ident, $method:ident($operand:literal), $result:literal, $($t:ty),+) => {$(
39+
let operand = $operand as $t;
40+
assert_eq!($result as $t, $op::$method(operand));
41+
assert_eq!($result as $t, $op::$method(&operand));
42+
)+};
43+
}
44+
45+
macro_rules! test_op {
46+
($fn_name:ident, $op:ident::$method:ident($lhs:literal, $rhs:literal), $result:literal, $($t:ty),+) => {
47+
#[test]
48+
fn $fn_name() {
49+
impls_defined!($op, $method($lhs, $rhs), $result, $($t),+);
50+
}
51+
};
52+
($fn_name:ident, $op:ident::$method:ident(&mut $lhs:literal, $rhs:literal), $result:literal, $($t:ty),+) => {
53+
#[test]
54+
fn $fn_name() {
55+
impls_defined!($op, $method(&mut $lhs, $rhs), $result, $($t),+);
56+
}
57+
};
58+
($fn_name:ident, $op:ident::$method:ident($lhs:literal), $result:literal, $($t:ty),+) => {
59+
#[test]
60+
fn $fn_name() {
61+
impls_defined!($op, $method($lhs), $result, $($t),+);
62+
}
63+
};
64+
}
65+
66+
test_op!(test_neg_defined, Neg::neg(0), 0, i8, i16, i32, i64, f32, f64);
67+
#[cfg(not(target_os = "emscripten"))]
68+
test_op!(test_neg_defined_128, Neg::neg(0), 0, i128);
69+
70+
test_op!(test_not_defined_bool, Not::not(true), false, bool);
71+
72+
macro_rules! test_arith_op {
73+
($fn_name:ident, $op:ident::$method:ident($lhs:literal, $rhs:literal)) => {
74+
#[test]
75+
fn $fn_name() {
76+
impls_defined!(
77+
$op,
78+
$method($lhs, $rhs),
79+
0,
80+
i8,
81+
i16,
82+
i32,
83+
i64,
84+
isize,
85+
u8,
86+
u16,
87+
u32,
88+
u64,
89+
usize,
90+
f32,
91+
f64
92+
);
93+
#[cfg(not(target_os = "emscripten"))]
94+
impls_defined!($op, $method($lhs, $rhs), 0, i128, u128);
95+
}
96+
};
97+
($fn_name:ident, $op:ident::$method:ident(&mut $lhs:literal, $rhs:literal)) => {
98+
#[test]
99+
fn $fn_name() {
100+
impls_defined!(
101+
$op,
102+
$method(&mut $lhs, $rhs),
103+
0,
104+
i8,
105+
i16,
106+
i32,
107+
i64,
108+
isize,
109+
u8,
110+
u16,
111+
u32,
112+
u64,
113+
usize,
114+
f32,
115+
f64
116+
);
117+
#[cfg(not(target_os = "emscripten"))]
118+
impls_defined!($op, $method(&mut $lhs, $rhs), 0, i128, u128);
119+
}
120+
};
121+
}
122+
123+
test_arith_op!(test_add_defined, Add::add(0, 0));
124+
test_arith_op!(test_add_assign_defined, AddAssign::add_assign(&mut 0, 0));
125+
test_arith_op!(test_sub_defined, Sub::sub(0, 0));
126+
test_arith_op!(test_sub_assign_defined, SubAssign::sub_assign(&mut 0, 0));
127+
test_arith_op!(test_mul_defined, Mul::mul(0, 0));
128+
test_arith_op!(test_mul_assign_defined, MulAssign::mul_assign(&mut 0, 0));
129+
test_arith_op!(test_div_defined, Div::div(0, 1));
130+
test_arith_op!(test_div_assign_defined, DivAssign::div_assign(&mut 0, 1));
131+
test_arith_op!(test_rem_defined, Rem::rem(0, 1));
132+
test_arith_op!(test_rem_assign_defined, RemAssign::rem_assign(&mut 0, 1));
133+
134+
macro_rules! test_bitop {
135+
($test_name:ident, $op:ident::$method:ident) => {
136+
#[test]
137+
fn $test_name() {
138+
impls_defined!(
139+
$op,
140+
$method(0, 0),
141+
0,
142+
i8,
143+
i16,
144+
i32,
145+
i64,
146+
isize,
147+
u8,
148+
u16,
149+
u32,
150+
u64,
151+
usize
152+
);
153+
#[cfg(not(target_os = "emscripten"))]
154+
impls_defined!($op, $method(0, 0), 0, i128, u128);
155+
impls_defined!($op, $method(false, false), false, bool);
156+
}
157+
};
158+
}
159+
macro_rules! test_bitop_assign {
160+
($test_name:ident, $op:ident::$method:ident) => {
161+
#[test]
162+
fn $test_name() {
163+
impls_defined!(
164+
$op,
165+
$method(&mut 0, 0),
166+
0,
167+
i8,
168+
i16,
169+
i32,
170+
i64,
171+
isize,
172+
u8,
173+
u16,
174+
u32,
175+
u64,
176+
usize
177+
);
178+
#[cfg(not(target_os = "emscripten"))]
179+
impls_defined!($op, $method(&mut 0, 0), 0, i128, u128);
180+
impls_defined!($op, $method(&mut false, false), false, bool);
181+
}
182+
};
183+
}
184+
185+
test_bitop!(test_bitand_defined, BitAnd::bitand);
186+
test_bitop_assign!(test_bitand_assign_defined, BitAndAssign::bitand_assign);
187+
test_bitop!(test_bitor_defined, BitOr::bitor);
188+
test_bitop_assign!(test_bitor_assign_defined, BitOrAssign::bitor_assign);
189+
test_bitop!(test_bitxor_defined, BitXor::bitxor);
190+
test_bitop_assign!(test_bitxor_assign_defined, BitXorAssign::bitxor_assign);
191+
192+
macro_rules! test_shift_inner {
193+
($op:ident::$method:ident, $lt:ty, $($rt:ty),+) => {
194+
$(impl_defined!($op, $method(0,0), 0, $lt, $rt);)+
195+
};
196+
($op:ident::$method:ident, $lt:ty) => {
197+
test_shift_inner!($op::$method, $lt, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
198+
#[cfg(not(target_os = "emscripten"))]
199+
test_shift_inner!($op::$method, $lt, i128, u128);
200+
};
201+
}
202+
203+
macro_rules! test_shift {
204+
($op:ident::$method:ident, $($lt:ty),+) => {
205+
$(test_shift_inner!($op::$method, $lt);)+
206+
};
207+
($test_name:ident, $op:ident::$method:ident) => {
208+
#[test]
209+
fn $test_name() {
210+
test_shift!($op::$method, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
211+
#[cfg(not(target_os = "emscripten"))]
212+
test_shift!($op::$method, i128, u128);
213+
}
214+
};
215+
}
216+
217+
macro_rules! test_shift_assign_inner {
218+
($op:ident::$method:ident, $lt:ty, $($rt:ty),+) => {
219+
$(impl_defined!($op, $method(&mut 0,0), 0, $lt, $rt);)+
220+
};
221+
($op:ident::$method:ident, $lt:ty) => {
222+
test_shift_assign_inner!($op::$method, $lt, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
223+
#[cfg(not(target_os = "emscripten"))]
224+
test_shift_assign_inner!($op::$method, $lt, i128, u128);
225+
};
226+
}
227+
228+
macro_rules! test_shift_assign {
229+
($op:ident::$method:ident, $($lt:ty),+) => {
230+
$(test_shift_assign_inner!($op::$method, $lt);)+
231+
};
232+
($test_name:ident, $op:ident::$method:ident) => {
233+
#[test]
234+
fn $test_name() {
235+
test_shift_assign!($op::$method, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
236+
#[cfg(not(target_os = "emscripten"))]
237+
test_shift_assign!($op::$method, i128, u128);
238+
}
239+
};
240+
}
241+
test_shift!(test_shl_defined, Shl::shl);
242+
test_shift_assign!(test_shl_assign_defined, ShlAssign::shl_assign);
243+
test_shift!(test_shr_defined, Shr::shr);
244+
test_shift_assign!(test_shr_assign_defined, ShrAssign::shr_assign);

library/core/tests/num/wrapping.rs

+15-14
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ macro_rules! wrapping_assignment {
2626
}
2727

2828
macro_rules! wrapping_test {
29-
($type:ty, $min:expr, $max:expr) => {
29+
($fn_name:ident, $type:ty, $min:expr, $max:expr) => {
3030
#[test]
31-
fn wrapping_$type() {
31+
fn $fn_name() {
3232
let zero: Wrapping<$type> = Wrapping(0);
3333
let one: Wrapping<$type> = Wrapping(1);
3434
let min: Wrapping<$type> = Wrapping($min);
@@ -60,23 +60,24 @@ macro_rules! wrapping_test {
6060
};
6161
}
6262

63-
wrapping_test!(i8, i8::MIN, i8::MAX);
64-
wrapping_test!(i16, i16::MIN, i16::MAX);
65-
wrapping_test!(i32, i32::MIN, i32::MAX);
66-
wrapping_test!(i64, i64::MIN, i64::MAX);
63+
wrapping_test!(test_wrapping_i8, i8, i8::MIN, i8::MAX);
64+
wrapping_test!(test_wrapping_i16, i16, i16::MIN, i16::MAX);
65+
wrapping_test!(test_wrapping_i32, i32, i32::MIN, i32::MAX);
66+
wrapping_test!(test_wrapping_i64, i64, i64::MIN, i64::MAX);
6767
#[cfg(not(target_os = "emscripten"))]
68-
wrapping_test!(i128, i128::MIN, i128::MAX);
69-
wrapping_test!(isize, isize::MIN, isize::MAX);
70-
wrapping_test!(u8, u8::MIN, u8::MAX);
71-
wrapping_test!(u16, u16::MIN, u16::MAX);
72-
wrapping_test!(u32, u32::MIN, u32::MAX);
73-
wrapping_test!(u64, u64::MIN, u64::MAX);
68+
wrapping_test!(test_wrapping_i128, i128, i128::MIN, i128::MAX);
69+
wrapping_test!(test_wrapping_isize, isize, isize::MIN, isize::MAX);
70+
wrapping_test!(test_wrapping_u8, u8, u8::MIN, u8::MAX);
71+
wrapping_test!(test_wrapping_u16, u16, u16::MIN, u16::MAX);
72+
wrapping_test!(test_wrapping_u32, u32, u32::MIN, u32::MAX);
73+
wrapping_test!(test_wrapping_u64, u64, u64::MIN, u64::MAX);
7474
#[cfg(not(target_os = "emscripten"))]
75-
wrapping_test!(u128, u128::MIN, u128::MAX);
76-
wrapping_test!(usize, usize::MIN, usize::MAX);
75+
wrapping_test!(test_wrapping_u128, u128, u128::MIN, u128::MAX);
76+
wrapping_test!(test_wrapping_usize, usize, usize::MIN, usize::MAX);
7777

7878
// Don't warn about overflowing ops on 32-bit platforms
7979
#[cfg_attr(target_pointer_width = "32", allow(const_err))]
80+
#[test]
8081
fn wrapping_int_api() {
8182
assert_eq!(i8::MAX.wrapping_add(1), i8::MIN);
8283
assert_eq!(i16::MAX.wrapping_add(1), i16::MIN);

0 commit comments

Comments
 (0)