Manual static dispatch

Allow determining default type of expressions in macros.

Probable syntax:

macro_rules! print_with_type {
    () => {println!()};
    
    ($x:expr) type $x {
        i32 => {println!("i32: {}", $x)},
        &str => {println!("str: {}", $x)},
    };
}

print_with_type!("abc"); // Output: "str: abc"
print_with_type!(123); // Output: "i32: 123"
print_with_type!(123u64); // Error: "unexpected token"

Possible use case:

macro_rules! anon_struct {
    () => {};
    
    ($($i:expr: $x:expr),+) type $x {
        $t => {
            {
                struct Inner {$(pub $i: $t),+}
                Inner {$($i: $x),+}
            }
        },
    };
}

let foo = anon_struct! {
    x: 15,
    y: 5.0f32,
    z: "abc",
};

println!("{}", foo.z);

Note that this anonymous structure implementation is just an example, not something ready to use since it's not generalized like tuples.

This syntax has many drawbacks and is not really flexible, but i needed to post this.

This isn't possible with the way macros currently work. You see, by the time type checking happens, all macros have been fully expanded already.

Conversely, to a macro all of its input is just a token stream, and it can't discern the semantics of the code represented by that token stream.

4 Likes

It's worth pointing out that this is in fact necessary, as macro expansion can result in changes to type resolution that could otherwise lead to circularities.

4 Likes

Of expressions is definitely not possible -- what's the type of Default::default()?

Could you rephrase your request in terms of the properties of tokens? For example, could you accomplish your goal if there was a new literal_string matcher that accepted string literals, but not integer literals, or similar?

Expanding your motivation would really help here. Why do you want this at macro expansion time? Why can't you phrase your "do different things for different types" with traits in your scenario?

Macros are probably not the best way to implement this… but generics can fit I guess :face_with_monocle:

Generic implementation would be much more restricted though. I think the idea is cornered.

Typed macros are very rare. I know julia has a (very, very restrictive) form of them, and Nim has them straight up, along with incremental type checking. Presumably the pull/query-based nature of rustc fits pretty well with incremental type checking, but it complicates the design of the language a lot (nim's type checking is very ad-hoc and frequently admits bogus stuff).

The cool thing you can do with this is allow macros to participate in the normal trait system, so for example having a macro as part of a trait. Again, it really complicates things tremendously.

You can do something similar with autoref, specialization, as does anyhow crate for its anyhow! macro.

See case-studies/README.md at master · dtolnay/case-studies · GitHub for more details

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