Skip to content

ACP: Negation functions for NonZeroI* #105

Closed

Description

Proposal

Problem statement

Integer primitives have functions such as overflowing_neg() for numeric negation with controlled overflow. These functions are currently missing from the core::num::NonZeroI{8,16,32,64} types.

Motivation, use-cases

Non-zero integers are frequently used to represent error codes from low-level OS APIs, because these APIs use 0 to indicate non-error. Some APIs use signed error codes as a form of namespacing, such as internal/public (FreeBSD) or kernel/userspace (Linux).

For example, the FUSE protocol uses userspace error codes (positive non-zero) but negates them when sending an error frame to the kernel.

// old
let (neg, _) = err.get().overflowing_neg();
let wire_neg = unsafe { NonZeroI32::new_unchecked(neg) };

// new
let (wire_neg, _) = err.overflowing_neg();

Solution sketches

Since the primitive integer types already have *_neg() functions, and negation can't return zero for non-zero inputs, writing wrappers for the non-zero integers is straightforward.

pub const fn is_negative(self) -> bool {
    self.get().is_negative()
}

pub const fn checked_neg(self) -> Option<$Ty> {
    if let Some(result) = self.get().checked_neg() {
        return Some(unsafe { $Ty::new_unchecked(result) });
    }
    None
}

pub const fn overflowing_neg(self) -> ($Ty, bool) {
    let (result, overflow) = self.get().overflowing_neg();
    ((unsafe { $Ty::new_unchecked(result) }), overflow)
}

pub const fn saturating_neg(self) -> $Ty {
    if let Some(result) = self.checked_neg() {
        return result;
    }
    unsafe { $Ty::new_unchecked(<$Int>::MAX) }
}

pub const fn wrapping_neg(self) -> $Ty {
    let result = self.get().wrapping_neg();
    unsafe { $Ty::new_unchecked(result) }
}

Links and related work

rust-lang/rust#89065
rust-lang/rust#84186

What happens now?

This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    ACP-acceptedAPI Change Proposal is accepted (seconded with no objections)T-libs-apiapi-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