1

I would like to write the equivalent of 2_u32, 7_i64, etc but where the numeric type is given by a type alias. e.g.,

type Number = u32;

fn main() {
    let a = 1_Number; // invalid syntax
    let b = 1_u32; // works, but isn't tied to `Number`
    let c = 1 as Number; // equivalent to `1_i32 as Number`, which is not what I want
    let d = Number::from(1) // requires `Number: From<i32>`, again not what I want
    let e = ???
}

So, is there a way to write “variable” numeric literal, whose type is that of a given type alias?

BallpointBen
  • 9,406
  • 1
  • 32
  • 62

1 Answers1

2

You can use type annotations:

let a: Number = 1;

Or, for inside nested expressions, you can create a macro to do that for you:

macro_rules! force_type {
    ($v:expr, $ty:ty $(,)?) => {{
        let v: $ty = $v;
        v
    }};
}

foo(force_type!(1, Number));

If you can limit yourself to literals, you can use a nicer syntax:

macro_rules! n {
    ($v:literal : $ty:ty) => {{
        let v: $ty = $v;
        v
    }}
}

foo(n!(1: Number));
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
  • The first works, but I'm actually hoping to use this in an expression, without assigning to an intermediate variable first (essentially I would like type ascription here). The second is explicitly not what I want, as it'll truncate if 1 is actually something like `u64::MAX`; I'd like it to be a compiler error the same way `let x: u8 = 256` is. – BallpointBen Jan 02 '23 at 20:02
  • 2
    Also possible, but super awkward: `foo(|| -> Number { 1 }());`. Note that this one relies on compiler optimization to not introduce overhead, which is not ideal in my opinion. – Finomnis Jan 02 '23 at 20:12
  • 3
    But honestly due to the [clean code principle of avoiding magic numbers](https://stackoverflow.com/questions/47882/what-is-a-magic-number-and-why-is-it-bad) you probably just want to declare them somewhere as `const MY_CONSTANT: type = value;` and then the entire problem is already solved. – Finomnis Jan 02 '23 at 20:18