Skip to content

Commit 69636ab

Browse files
authored
Unrolled build for #143949
Rollup merge of #143949 - clarfonthey:const-arith-ops, r=Amanieu Constify remaining traits/impls for `const_ops` Tracking issue: #143802 This is split into two commits for ease of reviewability: 1. Updates the `forward_ref_*` macros to accept multiple attributes (in anticipation of needing `rust_const_unstable` attributes) and also *require* attributes in these macros. Since the default attribute only helps for the initial implementations, it means it's easy to get wrong for future implementations, as shown for the saturating implementations which were incorrect before. 2. Actually constify the traits/impls. A few random other notes on the implementation specifically: * I unindented the attributes that were passed to the `forward_ref_*` macro calls because in some places rustfmt wanted them to be unindented, and in others it was allowed because they were themselves inside of macro bodies. I chose the consistent indenting even though I (personally) think it looks worse. ---- As far as the actual changes go, this constifies the following additional traits: * `Neg` * `Not` * `BitAnd` * `BitOr` * `BitXor` * `Shl` * `Shr` * `AddAssign` * `SubAssign` * `MulAssign` * `DivAssign` * `RemAssign` * `BitAndAssign` * `BitOrAssign` * `BitXorAssign` * `ShlAssign` * `ShrAssign` In terms of constified implementations of these traits, it adds the reference-forwarded versions of all the arithmetic operators, which are defined by the macros in `library/core/src/internal_macros.rs`. I'm not going to fully enumerate these because we'd be here all day, but sufficed to say, it effectively allows adding an `&` to one or both sides of an operator for primitives. Additionally, I constified the implementations for `Wrapping`, `Saturating`, and `NonZero` as well, since all of them forward to already-const-stable methods. (potentially via intrinsics, to avoid extra overhead) There are three "non-primitive" types which implement these traits, listed below. Note that I put "non-primitive" in quotes since I'm including `Wrapping`, `Saturating`, and `NonZero`, which are just wrappers over primitives. * `Duration` (arithmetic operations) * `SystemTime` (arithmetic operations) * `Ipv4Addr` (bit operations) * `Ipv6Addr` (bit operations) Additionally, because the methods on `SystemTime` needed to make these operations const were not marked const, a separate tracking issue for const-stabilising those methods is #144517. Stuff left out of this PR: * `Assume` (this could trivially be made const, but since the docs indicate this is still under heavy design, I figured I'd leave it out) * `Instant` (this could be made const, but cannot reasonably be constructed at constant time, so, isn't useful) * `SystemTime` (will submit separate PR) * SIMD types (I'm tackling these all at once later; see rust-lang/portable-simd#467) <!-- TRIAGEBOT_START --> <!-- TRIAGEBOT_CONCERN-ISSUE_START --> > [!NOTE] > # Concerns (0 active) > > - ~~[May break Clippy](#143949 (comment) resolved in [this comment](#143949 (comment)) > > *Managed by ```@rustbot`—see`` [help](https://forge.rust-lang.org/triagebot/concern.html) for details.* <!-- TRIAGEBOT_CONCERN-ISSUE_END --> <!-- TRIAGEBOT_END -->
2 parents 21a19c2 + bb32e31 commit 69636ab

File tree

9 files changed

+517
-240
lines changed

9 files changed

+517
-240
lines changed

library/core/src/internal_macros.rs

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
// implements the unary operator "op &T"
22
// based on "op T" where T is expected to be `Copy`able
33
macro_rules! forward_ref_unop {
4-
(impl $imp:ident, $method:ident for $t:ty) => {
5-
forward_ref_unop!(impl $imp, $method for $t,
6-
#[stable(feature = "rust1", since = "1.0.0")]);
7-
};
8-
(impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => {
9-
#[$attr]
10-
impl $imp for &$t {
4+
(impl $imp:ident, $method:ident for $t:ty, $(#[$attr:meta])+) => {
5+
$(#[$attr])+
6+
impl const $imp for &$t {
117
type Output = <$t as $imp>::Output;
128

139
#[inline]
@@ -21,13 +17,9 @@ macro_rules! forward_ref_unop {
2117
// implements binary operators "&T op U", "T op &U", "&T op &U"
2218
// based on "T op U" where T and U are expected to be `Copy`able
2319
macro_rules! forward_ref_binop {
24-
(impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
25-
forward_ref_binop!(impl $imp, $method for $t, $u,
26-
#[stable(feature = "rust1", since = "1.0.0")]);
27-
};
28-
(impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
29-
#[$attr]
30-
impl<'a> $imp<$u> for &'a $t {
20+
(impl $imp:ident, $method:ident for $t:ty, $u:ty, $(#[$attr:meta])+) => {
21+
$(#[$attr])+
22+
impl const $imp<$u> for &$t {
3123
type Output = <$t as $imp<$u>>::Output;
3224

3325
#[inline]
@@ -37,8 +29,8 @@ macro_rules! forward_ref_binop {
3729
}
3830
}
3931

40-
#[$attr]
41-
impl $imp<&$u> for $t {
32+
$(#[$attr])+
33+
impl const $imp<&$u> for $t {
4234
type Output = <$t as $imp<$u>>::Output;
4335

4436
#[inline]
@@ -48,8 +40,8 @@ macro_rules! forward_ref_binop {
4840
}
4941
}
5042

51-
#[$attr]
52-
impl $imp<&$u> for &$t {
43+
$(#[$attr])+
44+
impl const $imp<&$u> for &$t {
5345
type Output = <$t as $imp<$u>>::Output;
5446

5547
#[inline]
@@ -64,13 +56,9 @@ macro_rules! forward_ref_binop {
6456
// implements "T op= &U", based on "T op= U"
6557
// where U is expected to be `Copy`able
6658
macro_rules! forward_ref_op_assign {
67-
(impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
68-
forward_ref_op_assign!(impl $imp, $method for $t, $u,
69-
#[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]);
70-
};
71-
(impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
72-
#[$attr]
73-
impl $imp<&$u> for $t {
59+
(impl $imp:ident, $method:ident for $t:ty, $u:ty, $(#[$attr:meta])+) => {
60+
$(#[$attr])+
61+
impl const $imp<&$u> for $t {
7462
#[inline]
7563
#[track_caller]
7664
fn $method(&mut self, other: &$u) {

library/core/src/net/ip_addr.rs

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use super::display_buffer::DisplayBuffer;
22
use crate::cmp::Ordering;
33
use crate::fmt::{self, Write};
44
use crate::hash::{Hash, Hasher};
5-
use crate::iter;
65
use crate::mem::transmute;
76
use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
87

@@ -2348,20 +2347,24 @@ impl const From<[u16; 8]> for IpAddr {
23482347
}
23492348

23502349
#[stable(feature = "ip_bitops", since = "1.75.0")]
2351-
impl Not for Ipv4Addr {
2350+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2351+
impl const Not for Ipv4Addr {
23522352
type Output = Ipv4Addr;
23532353

23542354
#[inline]
23552355
fn not(mut self) -> Ipv4Addr {
2356-
for octet in &mut self.octets {
2357-
*octet = !*octet;
2356+
let mut idx = 0;
2357+
while idx < 4 {
2358+
self.octets[idx] = !self.octets[idx];
2359+
idx += 1;
23582360
}
23592361
self
23602362
}
23612363
}
23622364

23632365
#[stable(feature = "ip_bitops", since = "1.75.0")]
2364-
impl Not for &'_ Ipv4Addr {
2366+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2367+
impl const Not for &'_ Ipv4Addr {
23652368
type Output = Ipv4Addr;
23662369

23672370
#[inline]
@@ -2371,20 +2374,24 @@ impl Not for &'_ Ipv4Addr {
23712374
}
23722375

23732376
#[stable(feature = "ip_bitops", since = "1.75.0")]
2374-
impl Not for Ipv6Addr {
2377+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2378+
impl const Not for Ipv6Addr {
23752379
type Output = Ipv6Addr;
23762380

23772381
#[inline]
23782382
fn not(mut self) -> Ipv6Addr {
2379-
for octet in &mut self.octets {
2380-
*octet = !*octet;
2383+
let mut idx = 0;
2384+
while idx < 16 {
2385+
self.octets[idx] = !self.octets[idx];
2386+
idx += 1;
23812387
}
23822388
self
23832389
}
23842390
}
23852391

23862392
#[stable(feature = "ip_bitops", since = "1.75.0")]
2387-
impl Not for &'_ Ipv6Addr {
2393+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2394+
impl const Not for &'_ Ipv6Addr {
23882395
type Output = Ipv6Addr;
23892396

23902397
#[inline]
@@ -2400,23 +2407,25 @@ macro_rules! bitop_impls {
24002407
)*) => {
24012408
$(
24022409
$(#[$attr])*
2403-
impl $BitOpAssign for $ty {
2410+
impl const $BitOpAssign for $ty {
24042411
fn $bitop_assign(&mut self, rhs: $ty) {
2405-
for (lhs, rhs) in iter::zip(&mut self.octets, rhs.octets) {
2406-
lhs.$bitop_assign(rhs);
2412+
let mut idx = 0;
2413+
while idx < self.octets.len() {
2414+
self.octets[idx].$bitop_assign(rhs.octets[idx]);
2415+
idx += 1;
24072416
}
24082417
}
24092418
}
24102419

24112420
$(#[$attr])*
2412-
impl $BitOpAssign<&'_ $ty> for $ty {
2421+
impl const $BitOpAssign<&'_ $ty> for $ty {
24132422
fn $bitop_assign(&mut self, rhs: &'_ $ty) {
24142423
self.$bitop_assign(*rhs);
24152424
}
24162425
}
24172426

24182427
$(#[$attr])*
2419-
impl $BitOp for $ty {
2428+
impl const $BitOp for $ty {
24202429
type Output = $ty;
24212430

24222431
#[inline]
@@ -2427,7 +2436,7 @@ macro_rules! bitop_impls {
24272436
}
24282437

24292438
$(#[$attr])*
2430-
impl $BitOp<&'_ $ty> for $ty {
2439+
impl const $BitOp<&'_ $ty> for $ty {
24312440
type Output = $ty;
24322441

24332442
#[inline]
@@ -2438,7 +2447,7 @@ macro_rules! bitop_impls {
24382447
}
24392448

24402449
$(#[$attr])*
2441-
impl $BitOp<$ty> for &'_ $ty {
2450+
impl const $BitOp<$ty> for &'_ $ty {
24422451
type Output = $ty;
24432452

24442453
#[inline]
@@ -2450,7 +2459,7 @@ macro_rules! bitop_impls {
24502459
}
24512460

24522461
$(#[$attr])*
2453-
impl $BitOp<&'_ $ty> for &'_ $ty {
2462+
impl const $BitOp<&'_ $ty> for &'_ $ty {
24542463
type Output = $ty;
24552464

24562465
#[inline]
@@ -2466,12 +2475,16 @@ macro_rules! bitop_impls {
24662475

24672476
bitop_impls! {
24682477
#[stable(feature = "ip_bitops", since = "1.75.0")]
2478+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
24692479
impl (BitAnd, BitAndAssign) for Ipv4Addr = (bitand, bitand_assign);
24702480
#[stable(feature = "ip_bitops", since = "1.75.0")]
2481+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
24712482
impl (BitOr, BitOrAssign) for Ipv4Addr = (bitor, bitor_assign);
24722483

24732484
#[stable(feature = "ip_bitops", since = "1.75.0")]
2485+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
24742486
impl (BitAnd, BitAndAssign) for Ipv6Addr = (bitand, bitand_assign);
24752487
#[stable(feature = "ip_bitops", since = "1.75.0")]
2488+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
24762489
impl (BitOr, BitOrAssign) for Ipv6Addr = (bitor, bitor_assign);
24772490
}

library/core/src/num/nonzero.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,10 @@ where
310310
}
311311

312312
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
313-
impl<T> BitOr for NonZero<T>
313+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
314+
impl<T> const BitOr for NonZero<T>
314315
where
315-
T: ZeroablePrimitive + BitOr<Output = T>,
316+
T: ZeroablePrimitive + [const] BitOr<Output = T>,
316317
{
317318
type Output = Self;
318319

@@ -324,9 +325,10 @@ where
324325
}
325326

326327
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
327-
impl<T> BitOr<T> for NonZero<T>
328+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
329+
impl<T> const BitOr<T> for NonZero<T>
328330
where
329-
T: ZeroablePrimitive + BitOr<Output = T>,
331+
T: ZeroablePrimitive + [const] BitOr<Output = T>,
330332
{
331333
type Output = Self;
332334

@@ -338,9 +340,10 @@ where
338340
}
339341

340342
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
341-
impl<T> BitOr<NonZero<T>> for T
343+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
344+
impl<T> const BitOr<NonZero<T>> for T
342345
where
343-
T: ZeroablePrimitive + BitOr<Output = T>,
346+
T: ZeroablePrimitive + [const] BitOr<Output = T>,
344347
{
345348
type Output = NonZero<T>;
346349

@@ -352,10 +355,11 @@ where
352355
}
353356

354357
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
355-
impl<T> BitOrAssign for NonZero<T>
358+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
359+
impl<T> const BitOrAssign for NonZero<T>
356360
where
357361
T: ZeroablePrimitive,
358-
Self: BitOr<Output = Self>,
362+
Self: [const] BitOr<Output = Self>,
359363
{
360364
#[inline]
361365
fn bitor_assign(&mut self, rhs: Self) {
@@ -364,10 +368,11 @@ where
364368
}
365369

366370
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
367-
impl<T> BitOrAssign<T> for NonZero<T>
371+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
372+
impl<T> const BitOrAssign<T> for NonZero<T>
368373
where
369374
T: ZeroablePrimitive,
370-
Self: BitOr<T, Output = Self>,
375+
Self: [const] BitOr<T, Output = Self>,
371376
{
372377
#[inline]
373378
fn bitor_assign(&mut self, rhs: T) {
@@ -1239,7 +1244,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
12391244
// Impls for unsigned nonzero types only.
12401245
(unsigned $Int:ty) => {
12411246
#[stable(feature = "nonzero_div", since = "1.51.0")]
1242-
impl Div<NonZero<$Int>> for $Int {
1247+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
1248+
impl const Div<NonZero<$Int>> for $Int {
12431249
type Output = $Int;
12441250

12451251
/// Same as `self / other.get()`, but because `other` is a `NonZero<_>`,
@@ -1257,7 +1263,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
12571263
}
12581264

12591265
#[stable(feature = "nonzero_div_assign", since = "1.79.0")]
1260-
impl DivAssign<NonZero<$Int>> for $Int {
1266+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
1267+
impl const DivAssign<NonZero<$Int>> for $Int {
12611268
/// Same as `self /= other.get()`, but because `other` is a `NonZero<_>`,
12621269
/// there's never a runtime check for division-by-zero.
12631270
///
@@ -1270,7 +1277,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
12701277
}
12711278

12721279
#[stable(feature = "nonzero_div", since = "1.51.0")]
1273-
impl Rem<NonZero<$Int>> for $Int {
1280+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
1281+
impl const Rem<NonZero<$Int>> for $Int {
12741282
type Output = $Int;
12751283

12761284
/// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
@@ -1283,7 +1291,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
12831291
}
12841292

12851293
#[stable(feature = "nonzero_div_assign", since = "1.79.0")]
1286-
impl RemAssign<NonZero<$Int>> for $Int {
1294+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
1295+
impl const RemAssign<NonZero<$Int>> for $Int {
12871296
/// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
12881297
#[inline]
12891298
fn rem_assign(&mut self, other: NonZero<$Int>) {
@@ -1323,7 +1332,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
13231332
// Impls for signed nonzero types only.
13241333
(signed $Int:ty) => {
13251334
#[stable(feature = "signed_nonzero_neg", since = "1.71.0")]
1326-
impl Neg for NonZero<$Int> {
1335+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
1336+
impl const Neg for NonZero<$Int> {
13271337
type Output = Self;
13281338

13291339
#[inline]
@@ -1334,7 +1344,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
13341344
}
13351345

13361346
forward_ref_unop! { impl Neg, neg for NonZero<$Int>,
1337-
#[stable(feature = "signed_nonzero_neg", since = "1.71.0")] }
1347+
#[stable(feature = "signed_nonzero_neg", since = "1.71.0")]
1348+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
13381349
};
13391350
}
13401351

0 commit comments

Comments
 (0)