`type_id!(expr)` is needed

Currently, the macro is based on tokens, however, sometimes, we need to extract the type of a given expression and form the tokens that constitute the type to participate in the calculation.

let i = 0; 
transform_type!(type_id!(i)); 

The built-in macro type_id!(i) will spell out the tokens that constitute the inferred type of i such that we can program the token sequence.

In the current compiler that cannot be implemented. Macro expansion happens before types are known, on a purely syntactical level, before names are resolved and types are inferred.

3 Likes

Also note that even if the type_id!(i) macro worked, this would first expand the transform_type! macro, thus getting the unexpanded type_id!(i) tokens

1 Like

It would have to be a macro like asm! that maps to an otherwise unawailable syntax node. The question is, is that feasable? Obviously the combination with transform_type wouldn't.

In addition to not being possible in today's compiler due to layering, if this even was possible it would be a huge cycle footgun, since macros can emit things that change how something ends up inferred -- especially if you use two different macros like this that end up depending on each other.

What are you actually trying to accomplish?

1 Like

I want to make type participate in calculation or to say, be programmable, which can make rust macro have partial abilities like C++ template metaprogramming.

Note that C++ template metaprogramming does not use the C++ macro system either, because C++ macros can't tell types either.

If you want to do template metaprogramming in Rust, I suggest you describe what you can't do with traits today that you wish you could.

I suggest you describe what you can't do with traits today that you wish you could.

For example:

fn show<T:Trait>(t:T){
   if constexpr typeid(T) == String{
     //Do something that String can do
   }else{
     //Do other things
  }
}

Trait here is a first-level requirement, but we do want some more accurate tests in the function body. Moreover, the variadic template parameter pack is lacking in the rust.

template<class ....T>
void fun(std::tuple<T...> tup){
    eat_element(std::get<T>(tup)...);
}

Expand the tuple.

The first example is possible with specialization, and widely used inside the standard library (though afaik there's still no real plan for how to get a sound version of specialization stabilized).

Variadic generics have been discussed a few times, I don't see how type_id! has any impact on it?

You can always use poor-man's specialization in the mean time:

fn show<T: Debug + Any>(t: T){
    if let Some(t) = <dyn Any>::downcast_ref::<String>(&t) {
        dbg!(t.capacity());
    } else {
        dbg!(t);
    }
}

https://play.rust-lang.org/?version=nightly&mode=release&edition=2021&gist=7b6fe7ec044f751ad815127b8b1a007e

6 Likes

It will defer the cost to the runtime, which may not be what we want, we want to control the cost within the compile-time.

show is still monomorphized for every type, so the optimizer will help mitigate or avoid the run-time cost.

2 Likes

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