Skip to content

Tracking Issue for checked bitshifts #144336

Open

Description

@Qelxiros

Feature gate: #![feature(exact_bitshifts)]

This is a tracking issue for checked bitshifts, i.e. bitshifts that can be losslessly reversed.
ACP: rust-lang/libs-team#570

Public API

impl iX/uX {
    // Shift succeeds if `shift < Self::BITS` and right shifting the result returns the original value.
    fn exact_shl(self, shift: u32) -> Option<Self>;
    unsafe fn unchecked_exact_shl(self, shift: u32) -> Self;

    // Shift succeeds if `shift < Self::BITS` and left shifting the result returns the original value.
    fn exact_shr(self, shift: u32) -> Option<Self>;
    unsafe fn unchecked_exact_shr(self, shift: u32) -> Self;
}

Steps / History

(Remember to update the S-tracking-* label when checking boxes.)

Unresolved Questions

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html ↩

Activity

  1. added
    T-libs-api[DEPRECATED; DO NOT USE]
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Jul 23, 2025
  2. Qelxiros commented on Jul 23, 2025

    @Qelxiros
    ContributorAuthor

    @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.

  3. lolbinarycat commented on Jul 23, 2025

    @lolbinarycat
    Contributor

    @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.

  4. Qelxiros commented on Jul 24, 2025

    @Qelxiros
    ContributorAuthor

    @rustbot label -S-tracking-unimplemented

  5. tgross35 commented on Sep 3, 2025

    @tgross35
    Member

    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.

  6. added 3 commits that reference this issue on Sep 5, 2025
  7. added a commit that references this issue on Sep 5, 2025
  8. added a commit that references this issue on Sep 9, 2025
  9. Amanieu commented on Oct 15, 2025

    @Amanieu
    Member

    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:

    Signature Shift out of range Non-exact shift result
    fn checked_exact_shl(self, rhs: Self) -> Option<Self> None None
    fn strict_exact_shl(self, rhs: Self) -> Self Panic Panic
    fn exact_shl(self, rhs: Self) -> Option<Self> Panic on debug, wrap on release (matches shl) None
    unsafe fn unchecked_exact_{shl,shr}(self, rhs: Self) -> Self UB UB

    (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?

  10. added 6 commits that reference this issue on Nov 10, 2025
  11. added a commit that references this issue on Nov 11, 2025
  12. added a commit that references this issue on Nov 30, 2025
  13. Apersoma commented on Apr 24, 2026

    @Apersoma
    Contributor

    I think it would make sense to implement these on NonZero as well since x.exact_sh*(y) will never be zero if x is not zero.

  14. Apersoma commented on Apr 24, 2026

    @Apersoma
    Contributor

    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.

    fn left_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.

  15. added
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    and removed
    T-libs-api[DEPRECATED; DO NOT USE]
    on Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions