typesrustaliasassociated-const

Why can't a type alias use associated constants from the original type in Rust?


Editor's note: As of Rust 1.43, this works as expected.


I have a type alias type CardId = u64; and I want to initialize it to the maximum number it can have through the std::u64::MAX constant. And was surprised to learn that I cannot do the same from the alias.

use std::u64;

type CardId = u64;

fn main() {
    let this_works = u64::MAX;
    let this_doesnt_work = CardId::MAX;

    println!("Max amount in integer: {} and {}", this_works, this_doesnt_work);
}

(Permalink to the playground)

I was expecting the MAX constant to be accessible from the type alias also. This would aid me when I would change the type to u32, and this causes the code to have two points where I would need to modify instead of just location of the type alias. Why was this decision made, and did I miss something which which maybe would make this possible?


Solution

  • Before Rust 1.43, constants such as std::u64::MAX were not associated constants of the u64 type but constants defined in a module called u64. This is legacy from when Rust didn't have associated constants.

    As of Rust 1.43, those constants are defined as associated constants of the corresponding types. There is currently an RFC opened to deprecate the modules. For now they are only "soft-deprecated" and the documentation notes:

    Constant std::u32::MAX

    pub const MAX: u32 = u32::max_value(); // 4_294_967_295u32
    

    The largest value that can be represented by this integer type. Use u32::MAX instead.

    (Emphasis is mine)

    Another way to do this is to use the associated const methods (eg. u32::max_value) which were added because constant methods were available before associated constant. Those are also soft-deprecated and the documentation notes:

    pub const fn max_value() -> u32
    

    This method is soft-deprecated.

    Although using it won’t cause compilation warning, new code should use u32::MAX instead.

    Returns the largest value that can be represented by this integer type.

    (Emphasis is not mine)


    Associated constants are also accessible via type aliases as you expect:

    struct Foo;
    
    impl Foo {
        const FOO: u32 = 42;
    }
    
    type Bar = Foo;
    
    fn main() {
        let this_works = Foo::FOO;
        let this_also_work = Bar::FOO;
    
        let this_works_too = u32::MAX; // As of Rust 1.43
    
        println!("The answer: {} and {} or {}", this_works, this_also_work, this_works_too);
    }
    

    (Permalink to the playground)