rust-lang / rust-lang/rfcs

Allow for self to be used inside blocks passed to macros

Open
#1,606 11 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

T-lang
Dominant language
Markdown
Stars
6.6k
Forks
1.7k
Avg merge
16h 14m
Merged PRs (30d)
1

Description

As reported in https://github.com/rust-lang/rust/issues/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)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the linked issue 15682 and the macro-hygiene discussion, then compare the proposed self-based and identifier-based macro examples in this issue. Done means the requested exception is specified and the shown macro usage is supported without breaking the nested-implementation case; no source files or tests are named here.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.