You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a tracking issue for checked bitshifts, i.e. bitshifts that can be losslessly reversed.
ACP: rust-lang/libs-team#570
Public API
impliX/uX {// Shift succeeds if `shift < Self::BITS` and right shifting the result returns the original value.fnexact_shl(self,shift:u32) -> Option<Self>;unsafefnunchecked_exact_shl(self,shift:u32) -> Self;// Shift succeeds if `shift < Self::BITS` and left shifting the result returns the original value.fnexact_shr(self,shift:u32) -> Option<Self>;unsafefnunchecked_exact_shr(self,shift:u32) -> Self;}
Steps / History
(Remember to update the S-tracking-* label when checking boxes.)
@lolbinarycat Are you still interested in implementing this? If not, please let me know so I know it's available. Regardless, rust-lang/libs-team#570 can be closed now.
@Qelxiros I'd get around to it eventually, but I've got a fairly long backlog, so if anyone wants to claim this issue, they're free to, just cc me on the implementation PR so I can take a look.
Is there much of a usecase for the unchecked_ versions of these? The backend is getting the same information as for unchecked_sh{l,r}, only the preconditions differ slightly. yes it can have this information, see rust-lang/libs-team#570 (comment). The initial PR just didn't have new intrinsics.
We discussed this in the @rust-lang/libs-api meeting today. We would like any API decided here to be consistent with the API for exact division (#139911) which we also discussed.
We found 4 behaviors that users might be desirable:
The reasoning behind these choices is that an out-of-range shift is likely to be a bug, while an inexact result is likely something that a user might want to check for.
We are confident that we would like to stabilize unchecked_exact_{shl,shr} as described here, but are less sure about the other ones. Are those something that you would see yourself using in practice?
The reasoning behind these choices is that an out-of-range shift is likely to be a bug, while an inexact result is likely something that a user might want to check for.
I partially disagree with this because code like this will have UB when x is zero even though it shouldn't. When the shift is out-of-range and it's not being applied to zero, its probably a bug though.
fnleft_align(x:u32) -> u32{let ctlz = x.leading_zeros();// SAFETY: leading zeros gives the maximum safe shift, unless// `x` is 0 where there is no maximum and it is always safe.unsafe{ x.unchecked_exact_shl(ctlz)}}
I also have other code in a project of mine that I would like to be able to use unchecked_exact_shr on to remove factors of 2 while telling the compile the value won't become zero if it wasn't already but I wouldn't be able to if this goes through.
Alternatively, a version of leading_zeros or trailing_zeros that returns 0 (or some other value less than the type's bitcount) when the input is zero would partially solve this problem. BITS-1 might make more sense so that x.trailing_zeros().min(y.trailing_zeros()) is still accurate for gcd functions and similar which are one of the main places I run into this.
Activity
Qelxiros commentedon Jul 23, 2025
@lolbinarycat Are you still interested in implementing this? If not, please let me know so I know it's available. Regardless, rust-lang/libs-team#570 can be closed now.
lolbinarycat commentedon Jul 23, 2025
@Qelxiros I'd get around to it eventually, but I've got a fairly long backlog, so if anyone wants to claim this issue, they're free to, just cc me on the implementation PR so I can take a look.
Qelxiros commentedon Jul 24, 2025
@rustbot label -S-tracking-unimplemented
tgross35 commentedon Sep 3, 2025
Is there much of a usecase for theyes it can have this information, see rust-lang/libs-team#570 (comment). The initial PR just didn't have new intrinsics.unchecked_versions of these? The backend is getting the same information as forunchecked_sh{l,r}, only the preconditions differ slightly.Rollup merge of rust-lang#144342 - Qelxiros:exact-bitshifts, r=tgross35
Rollup merge of rust-lang#144342 - Qelxiros:exact-bitshifts, r=tgross35
Rollup merge of rust-lang#144342 - Qelxiros:exact-bitshifts, r=tgross35
Unrolled build for #144342
Rollup merge of rust-lang#144342 - Qelxiros:exact-bitshifts, r=tgross35
Amanieu commentedon Oct 15, 2025
We discussed this in the @rust-lang/libs-api meeting today. We would like any API decided here to be consistent with the API for exact division (#139911) which we also discussed.
We found 4 behaviors that users might be desirable:
fn checked_exact_shl(self, rhs: Self) -> Option<Self>NoneNonefn strict_exact_shl(self, rhs: Self) -> Selffn exact_shl(self, rhs: Self) -> Option<Self>shl)Noneunsafe fn unchecked_exact_{shl,shr}(self, rhs: Self) -> Self(same with
exact_shr)The reasoning behind these choices is that an out-of-range shift is likely to be a bug, while an inexact result is likely something that a user might want to check for.
We are confident that we would like to stabilize
unchecked_exact_{shl,shr}as described here, but are less sure about the other ones. Are those something that you would see yourself using in practice?Rollup merge of rust-lang#147771 - nxsaken:div_shlr_exact, r=dtolnay
Rollup merge of rust-lang#147771 - nxsaken:div_shlr_exact, r=dtolnay
Rollup merge of rust-lang#147771 - nxsaken:div_shlr_exact, r=dtolnay
Rollup merge of rust-lang#147771 - nxsaken:div_shlr_exact, r=dtolnay
Rollup merge of rust-lang#147771 - nxsaken:div_shlr_exact, r=dtolnay
Rollup merge of rust-lang#147771 - nxsaken:div_shlr_exact, r=dtolnay
Unrolled build for #147771
Rollup merge of #147771 - nxsaken:div_shlr_exact, r=dtolnay
Rollup merge of rust-lang#147771 - nxsaken:div_shlr_exact, r=dtolnay
Apersoma commentedon Apr 24, 2026
I think it would make sense to implement these on
NonZeroas well sincex.exact_sh*(y)will never be zero if x is not zero.Apersoma commentedon Apr 24, 2026
I partially disagree with this because code like this will have UB when
xis zero even though it shouldn't. When the shift is out-of-range and it's not being applied to zero, its probably a bug though.I also have other code in a project of mine that I would like to be able to use
unchecked_exact_shron to remove factors of 2 while telling the compile the value won't become zero if it wasn't already but I wouldn't be able to if this goes through.Alternatively, a version of
leading_zerosortrailing_zerosthat returns 0 (or some other value less than the type's bitcount) when the input is zero would partially solve this problem. BITS-1 might make more sense so thatx.trailing_zeros().min(y.trailing_zeros())is still accurate for gcd functions and similar which are one of the main places I run into this.Add contracts for unchecked_{shl,shr}_exact