# \<int\_ty\>::IS\_SIGNED

**URL:** <https://internals.rust-lang.org/t/int-ty-is-signed/14298>\
**Category:** libs\
**Created:** [March 19, 2021, 11:14am UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298 "2021-03-19T11:14:36Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [March 19, 2021, 11:14am UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/1 "2021-03-19T11:14:37Z")

</div>

I was writing some generic (macro) code...

```rust
let src_is_signed = <$x>::MIN < 0;
let dst_is_signed = <$y>::MIN < 0;

```

... and I get this warning, with no way to silence it:

```rust
warning: comparison is useless due to type limits
   --> src/lib.rs:160:37
    |
160 | let dst_is_signed = <$y>::MIN < 0;
    | ^^^^^^^^^^^^^
...
195 | impl_int_generic!(u64: isize, usize);
    | ------------------------------------- in this macro invocation
    |
    = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

```

So, is time for `<int_ty>::IS_SIGNED` (in the vein of [associated `BITS` constants](https://github.com/rust-lang/rust/pull/76492)), or perhaps an option to turn off this warning is enough?

---

<div class="post-metadata">

**Author:** ![tspiteri](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tspiteri/32/7283_2.png) [@tspiteri](https://internals.rust-lang.org/u/tspiteri)\
**Post date:** [March 19, 2021, 11:54am UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/2 "2021-03-19T11:54:35Z")

</div>

You could use `MIN.count_ones() > 0` which works without warning, and can be used in constant context.

Edit: Or `MIN != 0`.

Edit: I would still find `IS_SIGNED` cleaner and useful.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [March 19, 2021, 6:17pm UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/3 "2021-03-19T18:17:44Z")

</div>

I would love to have `IS_SIGNED`, and various other constants and methods. I think they'd provide much more value if they were part of a sealed trait that numeric types implemented, though. That would make it easy to write generic code over numeric types, whether using macros or generic functions.

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [March 19, 2021, 6:22pm UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/4 "2021-03-19T18:22:54Z")

</div>

I also want a way to convert between an unsigned to signed variants of the same width in a fully generic way. Specifically, given u32 or i32, being able to get u32 or i32 specifically.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [March 19, 2021, 8:47pm UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/5 "2021-03-19T20:47:36Z")

</div>

Are you implying that you'd prefer some traits from the num crate be uplifted to core?

---

<div class="post-metadata">

**Author:** ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)\
**Post date:** [March 19, 2021, 8:52pm UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/6 "2021-03-19T20:52:18Z")

</div>

Another possible workaround:

```rust
fn lt<T: PartialOrd>(a: T, b: T) -> bool {
    a < b
}
fn foo() {
    let is_signed: bool = lt(i32::MIN, 0);
}

```

…though this doesn't work in `const` context, yet.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [March 20, 2021, 3:27am UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/8 "2021-03-20T03:27:30Z")

</div>

Yes, absolutely, though I'm suggesting that at least at first it may make sense for them to be sealed to make it easier to extend them in the future.

---

<div class="post-metadata">

**Author:** ![tspiteri](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tspiteri/32/7283_2.png) [@tspiteri](https://internals.rust-lang.org/u/tspiteri)\
**Post date:** [March 20, 2021, 2:59pm UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/9 "2021-03-20T14:59:00Z")

</div>

The num-traits crate seems to cater for two distinct needs:

1. traits for generalizing code over primitives
2. traits that can be implemented for user types

Item 1 above is better served with sealed traits, as these can be updated with all the new features. However, sealing will block item 2. It seems to me that it is not possible to satisfy both needs with the same traits. I'd prefer sealed traits that are kept up to date in the standard library.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [March 20, 2021, 6:16pm UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/10 "2021-03-20T18:16:18Z")

</div>

Exactly. I feel like the desire to make (2) perfect and handle backwards compatibility has prevented doing (1) in the standard library.

Adding a required method or type or constant to a non-sealed trait is a breaking change. But we can extend a sealed trait.

So, I'd favor putting a few sealed numeric traits in the standard library, whose primary purpose is to abstract over primitive types, and especially to abstract over things that are currently only available via intrinsic methods of numerics (and thus to macros but not generic functions).

None of that should supplant the third-party crate ecosystem, which can provide non-sealed numeric traits for user-defined numeric types.

---

<div class="post-metadata">

**Author:** ![SlightlyOutOfPhase](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/slightlyoutofphase/32/5440_2.png) [@SlightlyOutOfPhase](https://internals.rust-lang.org/u/SlightlyOutOfPhase)\
**Post date:** [March 22, 2021, 4:05pm UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/11 "2021-03-22T16:05:02Z")

</div>

Obviously a more official / far less "hacky" solution would be preferable, but if you need this functionality right now and are able to use nightly feature flags, it's not actually difficult to implement in a way that even works in `const` contexts:

```rust
#![feature(const_type_name)]

use std::any::type_name;

// By directly calling `type_name` here we guarantee that the names
// remain "up to date".
const I8_NAME: &str = type_name::<i8>();
const I16_NAME: &str = type_name::<i16>();
const I32_NAME: &str = type_name::<i32>();
const I64_NAME: &str = type_name::<i64>();
const I128_NAME: &str = type_name::<i128>();
const ISIZE_NAME: &str = type_name::<isize>();
const F32_NAME: &str = type_name::<f32>();
const F64_NAME: &str = type_name::<f64>();
const SIGNED_TYPES: [&str; 8] = [
    I8_NAME, I16_NAME, I32_NAME, I64_NAME,
    I128_NAME, ISIZE_NAME, F32_NAME, F64_NAME,
];

const fn const_cmp_str(lhs: &str, rhs: &str) -> bool {
    // Obviously the below code only makes sense in the context of
    // calling it at compile-time with constant input for both `lhs`
    // and `rhs`.
    let lhs_bytes = lhs.as_bytes();
    let rhs_bytes = rhs.as_bytes();
    if lhs_bytes.len() != rhs_bytes.len() {
        return false;
    }
    let mut i = 0;
    while i < lhs_bytes.len() {
        if lhs_bytes[i] != rhs_bytes[i] {
            return false;
        }
        i += 1;
    }
    true
}

const fn is_signed_internal<T: ?Sized>() -> bool {
    let mut i = 0;
    // `for x in y` does not work in const contexts yet.
    while i < SIGNED_TYPES.len() {
        // Can't do `SIGNED_TYPES[i] == type_name::<T>()` and have this
        // be `const`.
        if const_cmp_str(SIGNED_TYPES[i], type_name::<T>()) {
            return true;
        }
        i += 1;
    }
    false
}

#[inline(always)]
pub const fn is_signed<T: ?Sized>() -> bool {
    is_signed_internal::<T>()
}

#[inline(always)]
pub const fn is_signed_value<T: ?Sized>(_val: &T) -> bool {
    is_signed_internal::<T>()
}

const B1: bool = is_signed::<i32>();
const B2: bool = is_signed_value(&12i128);
const B3: bool = is_signed::<f64>();
const B4: bool = is_signed_value(&12.24599);
const B5: bool = is_signed::<u32>();
const B6: bool = is_signed_value(&900u32);
const B7: bool = is_signed::<u16>();
const B8: bool = is_signed_value("hello");

fn main() {
    println!(
        "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
        B1, B2, B3, B4, B5, B6, B7, B8
    );
}

```

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [March 23, 2021, 8:22am UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/12 "2021-03-23T08:22:39Z")

</div>

Agreed, a sealed trait in std would be nice. But what should it contain besides `IS_SIGNED`?

Moving things like `i32::MIN` or `i32::leading_zeros()` to a new trait is a breaking change (even if the new trait is in the prelude due to inference in the case a user trait implements consts/methods of the same names on the same types).

Having those methods and consts defined on the types _and_ on the new sealed trait should work I guess.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [March 23, 2021, 3:04pm UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/13 "2021-03-23T15:04:17Z")

</div>

Yes, the inherent versions would have to remain as well, for compatibility.

---

<div class="post-metadata">

**Author:** ![tspiteri](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tspiteri/32/7283_2.png) [@tspiteri](https://internals.rust-lang.org/u/tspiteri)\
**Post date:** [March 26, 2021, 6:27pm UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/14 "2021-03-26T18:27:22Z")

</div>

By the way, I get ideas form irlo/PRs all the time and implement them in the [fixed](https://docs.rs/fixed/1/fixed) crate, as there I don't need to be as careful as the standard library in adding new features.

One thing I've had since 0.4 back in 2019 is three sealed traits for a generic way to access all the methods. The [`Fixed`](https://docs.rs/fixed/1/fixed/traits/trait.Fixed.html) trait is implemented for all fixed-point numbers, the [`FixedSigned`](https://docs.rs/fixed/1/fixed/traits/trait.FixedSigned.html) trait is implemented for all signed numbers (and has `Fixed` as a supertrait), and [`FixedUnsigned`](https://docs.rs/fixed/1/fixed/traits/trait.FixedUnsigned.html) is implemented for all unsigned numbers (with `Fixed` as a supertrait). Since they're sealed, I add most new inherent methods and associated constants in the appropriate trait of the three.

Now I've just added [`IS_SIGNED`](https://docs.rs/fixed/1/fixed/struct.FixedI32.html#associatedconstant.IS_SIGNED). I added it as both an inherent associated constant, so that users do not have to import the trait; and as a [trait associated constant](https://docs.rs/fixed/1/fixed/traits/trait.Fixed.html#associatedconstant.IS_SIGNED), so that it can be used in generic code. I don't seem to have any issues yet because of adding methods/constants both in the inherent impl and in the traits.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [June 24, 2021, 6:27pm UTC](https://internals.rust-lang.org/t/int-ty-is-signed/14298/15 "2021-06-24T18:27:28Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
