Stream: t-compiler/wg-rls-2.0

Topic: Support bulitin macros

Edwin Cheng (Nov 05 2019 at 04:56, on Zulip):

I am starting to work on adding builtin macros. (e.g: concat!) . My initial thought is to create each custom MacroDef for each builtin macros and registers these in the beginning of module collecting phase. Basically changing MacroDef as following:

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MacroDefId {

// `MacroDefSource` is the normal MacroDef
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroDefSource {
    pub krate: CrateId,
    pub ast_id: AstId<ast::MacroCall>,

Another option is to add a new type ModuleDef::BultinMacro and handle it separately (Although I hadn't figured out the whole path for how to do it)

Do anyone have any idea?

Edwin Cheng (Nov 05 2019 at 16:04, on Zulip):

@matklad After studying how rustc implement concat! macro, I finally understand what you mean "include! and concat! seem to use "eager expansion" of some sorts.".

For example:

macro_rules! foo {
    () => {a}
fn main() {
    println!("{}", concat!(foo!(), bar!()));

When we try to expand concat!, we have to expand foo!() and bar!() first. And this order is different from what normal mbe is handled.

matklad (Nov 06 2019 at 09:53, on Zulip):

@Edwin Cheng yeah, I think we need to extend MacroDefId. I imagine, in the end it might want to look like

enum MacroDefId {

I think it makes sense to just hard-code bulitin macrod right now for simplicity (so, don't add them to ModuleDef), but, long term, I think nameres should be aware of such macros.

matklad (Nov 06 2019 at 09:55, on Zulip):

And yeah, the hardest part about build-in macros is that they are not necessary restricted to tt -> tt interface, and might do all sorts of weird call-backs into the compiler. I hope we can handle them clearly withing hir_expand framework, but we must brace ourselves for the worst just in case :)

Edwin Cheng (Nov 07 2019 at 13:14, on Zulip):

I just checked, seem like there are only 2 builtin macros which use eagar expansion. So my first MVP will be implement line! macro first. It seem like not depending on anything complicated.

Edwin Cheng (Nov 07 2019 at 13:14, on Zulip):

Another question:, I found that for every builtin macro, An attribute rustc_builtin_macro must be used. link. But I don't know it is a good idea depends on it to recognize the input path as bultin-macro because I don't know how stable it is.

On the other hand, it simplifies the whole builtin macro name resolution alot; We could just mark the macro in name resolution phase as builtin, and handle it in ModCollector.

matklad (Nov 07 2019 at 13:16, on Zulip):

@Edwin Cheng that attribute is a relatively new addition, but I think we can rely on it

matklad (Nov 07 2019 at 13:16, on Zulip):

Even if it breaks later, we can just fix the code

Edwin Cheng (Nov 13 2019 at 14:11, on Zulip):

I figure out how to do eager macro expansion in current infrastructure finally and implemented concat!. However I can’t test it in whole def collection phase since there’s no way to expand it before include! is implemented. 🙄

matklad (Nov 13 2019 at 14:13, on Zulip):

hm..... Should we have dedicated macro expansion tests for built-in macros?

Edwin Cheng (Nov 13 2019 at 15:30, on Zulip):

Yes, sure we should. However, the actual problem here is: To test the macro name resolution in items scope, we have to start with a macro which expand to Macro::Items, concat itself only expands to expr. Of course I can write a test for it without triggering eager expansion but it is not ideal.

matklad (Nov 13 2019 at 15:32, on Zulip):

Hm, and I guess, we need name-resolution to write non-trivial test cases?

Like, it seems like it should be possible to test macro expansion without nameres, in theory, but in practice you need name resolution for interesting test cases

Last update: Sep 30 2020 at 16:45UTC