Description
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)