Can't generate non-static method using compiler plugin


#1

Latest nightly rustc broke my mockers library. Generated methods now can’t be compiled, failing with message “self is not available in a static method. Maybe a self argument is missing? [E0424]”.

The strange thing is that I have two ways to generate mock: custom derive clause and macro call. Custom derive clause receives parsed item description and macro parses item itself, but they both ways uses the same code-generation functions. And derive still works, but macro doesn’t. I can’t understand why.

I have extracted smallest plugin reproducing problem to https://github.com/kriomant/mockers_problem

$ cargo test
   Compiling mockers_problem v0.0.1 (file:///Users/kriomant/from_self/mockers_macros)
tests/lib.rs:9:1: 14:2 error: `self` is not available in a static method. Maybe a `self` argument is missing? [E0424]
tests/lib.rs:9 mock!{
               ^
<std macros>:9:3: 9:42 note: in this expansion of format_args!
<std macros>:5:1: 7:6 note: in this expansion of panic! (defined in <std macros>)
tests/lib.rs:9:1: 14:2 note: in this expansion of unreachable! (defined in <std macros>)
tests/lib.rs:9:1: 14:2 note: in this expansion of mock! (defined in tests/lib.rs)
tests/lib.rs:9:1: 14:2 help: run `rustc --explain E0424` to see a detailed explanation
error: aborting due to previous error
error: Could not compile `mockers_problem`.

To learn more, run the command again with --verbose.

I have used -Z unstable-options --pretty=expanded to view generated code and it seems to be identical.


#2

This might be related to https://github.com/rust-lang/rust/pull/33505?


#3

Yes, this happened on the same rustc update which declared new_self as deprecated in favor of from_self. I have replaced new_self with from_self, so deprecation warning went away, but library now can’t be compiled.


#5

It can’t be, that’s a HIR change


#6

Ahh, I just got the same error without using a plugin.

That’s a really confusing error message, but it means the problem is with hygiene.
You need to reuse the same self identifier found in SelfKind, or replace it with an identifier without hygiene restrictions, i.e. something more like the quasi-quoted method body you have self in atm.


#7

Thanks, I have fixed it by using:

    let self_ident = match self_kind {
        &SelfKind::Static => unreachable!(),
        &SelfKind::Value(ident) => ident,
        &SelfKind::Region(_, _, ident) => ident,
        &SelfKind::Explicit(_, ident) => ident,
    };
    quote_block!(cx, ... $self_ident.field ...).unwrap();

But still: is this self behavior change in quote_* bug or fix?


#8

It looks like a hygiene bug fix to me.
There’s also an upcoming change removing ExplicitSelf and SelfKind from the AST, AFAICT.