Compile time: proc macro vs generic

If you have code that can either be generated by

(1) proc macro

OR

(2) proc macro calling some generic code with type arguments

Is it generally to go with (1) instead of (2) to avoid monomorphization / ensuring the code is only "processed" once ?

Thanks!

If you can do something with the type system, do it with the type system. Macros are for generating the parts that you can't express using types and generics.

2 Likes

That's great. The point of this post is optimizing for compile time.

Monomorphization involves passing the fully type-checked, borrow-checked and elaborated MIR code into LLVM, instantiating it with concrete types. Calling a proc macro instead generates a dump of unparsed tokens, nevermind any type-checking. It's hard to imagine why you would think that the former is slower than the latter.

1 Like

crate header:

impl ... {
    pub fn to_untyped2(&self) -> ... {
        <Self as ...>::to_untyped(self)
    }
}

crate usage:

blah.to_untyped2() is much faster than blah.to_untyped() to compile, by around 500 milliseconds -- from eyeballing cargo build --timings a few times

The reason: It appears that in .to_untyped2(), crate usage merely creates a ptr to whatever crate_header expanded

In .to_untyped(), crate_usage appears to be RE_EXPANDING whateever crate_header expanded

Here, by introducing an extra function .to_untyped2(), we seem to "cache the generic expansion / instantiation of .to_untyped()"

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.