Skip to content

ACP: wrapping/checked/unbounded funnel shifts #855

Description

@pthariensflame

Proposal

Problem statement

Funnel shifts have been approved in #642, including asking for wrapping funnel shifts, but those have not been implemented. Additional useful variations of funnel shifts include checked and unbounded versions.

Motivating examples or use cases

The same motivations apply as in #642 for wrapping funnel shifts.

Checked funnel shifts are useful for:

  • giving recoverable errors when a shift amount is beyond the bitwidth of the type, for example if the shift amount is end-user-supplied; and
  • implementing more situation-specific behaviors when a shift amount is beyond the bitwidth of the type.
    • In fact, panicking and unbounded funnel shifts are both more cleanly implemented by delegating to checked ones.

Unbounded funnel shifts are useful in similar circumstances to the existing unbounded non-funnel shifts, especially on wider types.
For example, u32::unbounded_funnel_{shl,shr} is the direction-relevant half of u64::unbounded_shr without needing to assemble and then disassemble the u64 from the u32s; u128::unbounded_funnel_{shl,shr} has no higher bitwidth to implement it with.

Solution sketch

A full implementation is available at rust-lang/rust#161119.

impl u{8,16,32,64,128,size} {
    // Already accepted and implemented as part of previous ACP; shown here only for context
    pub const fn funnel_shl(self, right: Self, n: u32) -> Self;
    pub const fn funnel_shr(self, right: Self, n: u32) -> Self;
    pub const unsafe fn unchecked_funnel_shl(self, right: Self, n: u32) -> Self;
    pub const unsafe fn unchecked_funnel_shr(self, right: Self, n: u32) -> Self;

    // Requested in previous ACP but never implemented; proposed again here
    pub const fn wrapping_funnel_shl(self, right: Self, n: u32) -> Self;
    pub const fn wrapping_funnel_shr(self, right: Self, n: u32) -> Self;

    // Proposed for the first time here
    pub const fn checked_funnel_shl(self, right: Self, n: u32) -> Option<Self>;
    pub const fn checked_funnel_shr(self, right: Self, n: u32) -> Option<Self>;
    pub const fn unbounded_funnel_shl(self, right: Self, n: u32) -> Self;
    pub const fn unbounded_funnel_shr(self, right: Self, n: u32) -> Self;
}

Alternatives

These functions could be open-coded anywhere they would be used, once the original {,unchecked}_funnel_{shl,shr} are stabilized (see also rust-lang/rust#161015).
This would be less than ideal, since it would decrease the clarity and readability of the resulting code.
It would be especially bad for the unbounded funnel shifts, since they are the "natural" way newcomers tend to expect funnel shifts to work and their absence may lead to the misuse of the more restrictive methods instead.

Links and related work

Tracking issue for the original funnel shift methods: rust-lang/rust#145686

What happens now?

This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.

Possible responses

The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):

  • We think this problem seems worth solving, and the standard library might be the right place to solve it.
  • We think that this probably doesn't belong in the standard library.

Second, if there's a concrete solution:

  • We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
  • We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-change-proposalA proposal to add or alter unstable APIs in the standard libraries

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions