Skip to content

Allow for self to be used inside blocks passed to macros #1606

Open
@tinco

Description

@tinco

As reported in rust-lang/rust#15682 it is currently not allowed use the word self in a block passed to a macro because of hygiene issues.

struct A {
    pub v: i64
}

macro_rules! pretty {
    ( $t:ty => $body:block ) => (
        impl $t {
            pub fn pretty(&self) -> String $body
        }
    )
}

pretty! (A => {
    format!("<A:{}>", self.v)
});

fn main() {
    println!("Pretty: {}", A { v: 3 }.pretty());
}

Proposal

I would like to propose to implement the workaround suggested by @Ryman and make an exception for the self keyword in the macro hygiene checker. Afterwards an issue/rfc can be made for a more complete solution.

Advantage

It will enable a class of macros that are currently unavailable. There are some workarounds but they make the macros less intuitive to use, for example the previous example could be written like this:

macro_rules! pretty {
    ( $t:ty, $_self:ident => $body:block ) => (
        impl $t {
            pub fn pretty(&$_self) -> String $body
        }
    )
}

And used like this:

pretty! (A, self => {
    format!("<A:{}>", self.v)
});

This works but is unintuitive and gives a confusing error when used with another ident than self.

Disadvantage

@huonw pointed out that this solution will break when an implementation is nested inside a method. This is valid of course, but to me it feels like a bit of a convoluted case. If it does happen in the real world I feel it would not likely fail silently, as both selfs would have to share an interface for the compilation to succeed.

Should this feature be blocked because it has no perfect solution right now? (A more complete suggestion was suggested by @Ryman but it looks to me like it would be a deep and complex hack)

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team, which will review and decide on the RFC.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions