Stream: t-compiler/rust-analyzer

Topic: macro-rules expansion not working?


Roland Kuhn (Feb 24 2021 at 20:25, on Zulip):

see this macro for an example: While for println! I get () as return type, the example macro yields {unknown} in rust-analyzer (in that repository there are tons of macros, and I couldn’t find one that was successfully expanded to yield type hints). Perhaps noteworthy is that the recursive expansion preview in VS Code shows only one level of expansion. It would be so super-nice if this would work because session types (what I’m working on) have some corner cases that just require some boilerplate, and I’d love to get rid of it.

Jonas Schievink [he/him] (Feb 24 2021 at 20:33, on Zulip):

We don't support macros in type position at the moment

Roland Kuhn (Feb 24 2021 at 20:48, on Zulip):

Hmm, but the expansion also stops for the value part:

{
  struct Rec {
    pub rec:rec!(@@1 Tx[RoleA,Rx[RoleB,rec]]),
  }fn new() -> Rec {
    Rec {
      rec:rec!(@@2 Tx[RoleA,Rx[RoleB,rec]]),
    }
  }new().rec
}
Roland Kuhn (Feb 24 2021 at 20:51, on Zulip):

In any case: how much is missing regarding macros in type position? Anything I could help with?

Jonas Schievink [he/him] (Feb 24 2021 at 21:10, on Zulip):

I'm not totally sure, but I think the first step is to duplicate TypeRef into the item_tree module and add a Macro variant to it. These then need to be lowered to the HIR-view TypeRef, at which point the macro needs to be expanded.

Roland Kuhn (Feb 24 2021 at 21:46, on Zulip):

I managed to simplify it even more, not using macros in type position, and I still get {unknown}:

struct RoleA;
struct RoleB;

struct Tx<Role, Cont> {
    cont: Cont,
    _ph: PhantomData<Role>,
}
impl<Role, Cont: Default> Default for Tx<Role, Cont> {
    fn default() -> Self {
        Self { cont: Cont::default(), _ph: PhantomData }
    }
}
struct Rx<Role, Cont> {
    cont: Cont,
    _ph: PhantomData<Role>,
}
impl<Role, Cont: Default> Default for Rx<Role, Cont> {
    fn default() -> Self {
        Self { cont: Cont::default(), _ph: PhantomData }
    }
}

macro_rules! rec {
    ($x:ident, $t:ty) => {{
        #[derive(Default)]
        struct $x;
        impl $x {
            pub fn rec(self) -> $t {
                Default::default()
            }
        }
        $x::default().rec()
    }};
}

fn rec_test() {
    let mut p = rec!(X, Tx<RoleA, Rx<RoleB, X>>);
}
Edwin Cheng (Feb 24 2021 at 21:59, on Zulip):

Your case above is not related to macro:

Simplified case :

fn main() {
    let _p = {
        struct X;
        impl X {
            pub fn foo(self) -> u32 {
                0
            }
        }
        X {}.foo()
    };
}
Jonas Schievink [he/him] (Feb 24 2021 at 22:52, on Zulip):

Ah, yes, we don't support impls inside blocks either

Jonas Schievink [he/him] (Feb 24 2021 at 22:52, on Zulip):

This is https://github.com/rust-analyzer/rust-analyzer/issues/7633

Roland Kuhn (Feb 25 2021 at 08:00, on Zulip):

Thanks, with this I was able to sidestep the issue by just putting the declaration on the module level!

Last update: Jul 29 2021 at 22:30UTC