Hello everybody,
I'm trying to use a macro to generate struct
s and corresponding impl
s for a specific trait -- see the code below or the playground at Rust Playground, but I'm failing by trying to use a variable in a block.
Specifically, the macro create_protocol
should create a struct Tcp
and implement the trait Protocol
`s single method send
with the code block that is passed as the macro`s second parameter. Now this fails, because the block is trying to use self
which - as far as I understand - does not work due to macro hygiene: the self
in the block is not the same as the self
in the implementation.
Interestingly, the generated code is correct. If I expand the macro via rustc -Z unstable-options --pretty expanded macro_test.rs > macro_expanded.rs
, I do receive the following error message:
macro_test.rs:18:38: 18:42 error: `self` is not available in a static method. Maybe a `self` argument is missing? [E0424]
macro_test.rs:18 let TcpConnect(ref challenge) = *self;
^~~~
macro_test.rs:17:1: 21:4 note: in this expansion of create_protocol! (defined in macro_test.rs)
macro_test.rs:18:38: 18:42 help: run `rustc --explain E0424` to see a detailed explanation
error: aborting due to previous error
But the expanded code does compile without errors: rustc macro_expanded.rs
.
There are open issues regarding the use of self
in macros like `self` variable in macros is broken (regression) · Issue #15682 · rust-lang/rust · GitHub, but I don't want to add to the discussion there. I'm just interested in how to solve this problem with the current capabilities of Rust macros.
Thanks for your help in advance,
Lukas
use std::io::Error;
pub trait Protocol {
fn send(self: &Self) -> Result<Vec<u8>, Error>;
}
macro_rules! create_protocol {
($protocol_name: ident, $send_code: block) => (
pub struct $protocol_name(pub Vec<u8>);
impl<'a> Protocol for $protocol_name {
fn send(&self) -> Result<Vec<u8>, Error> $send_code
}
)
}
create_protocol!(Tcp, {
let Tcp(ref data) = *self;
// Do stuff with data
Ok(vec![0u8; 10])
});
fn main() {}