0

I'm having a lot of trouble getting macros from another crate to work in Rust. My lib.rs file looks like this:

#[macro_use]
extern crate session_types;

mod main;

And here's a simplified part of my main.rs, demonstrating proper use of the offer! macro:

use session_types::*;

type Server = Offer<Choose<Var<Z>, Var<Z>>, Choose<Var<Z>, Var<Z>>>;

struct Foo;

impl Foo {
    fn server(&self, c: Chan<(), Rec<Server>>) {
        let mut c = c.enter();
        loop {
            c = offer!{ c,
                LEFT_BRANCH => c.sel1().zero(),
                RIGHT_BRANCH => c.sel2().zero()
            };
        }
    }
}

I know the compiler is able to expand offer! because I've debugged code in blocks inside that macro, and I get warnings about unused variables in that macro which look like this:

<session_types macros>:1:1: 5:16 note: in expansion of offer!
src/main.rs:107:21: 133:14 note: expansion site
<session_types macros>:3:53: 3:57: warning: unused variable: 'right', #[warn(unused_variables)] on by default
<session_types macros>:3 Branch:: Left ( $id ) => $code, Branch:: Right ( $id ) => offer! {

which obviously includes part of the macro. However, I get compilation errors saying that, on the lines they're used, the macro offer! is undefined.

src/main.rs:107:21: 133:14 note: in this expansion of offer! (defined in <session_types macros>)
src/main.rs:57:17: 57:22 error: macro undefined: 'offer!'
src/main.rs:57             c = offer!{ c,
                               ^~~~~
src/main.rs:107:21: 107:26 error: macro undefined: 'offer!'
src/main.rs:107             night = offer!{ night,

Note: this occurs on the nightly branch of the compiler.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
zrneely
  • 1,802
  • 3
  • 17
  • 26
  • Your question makes no sense. You say that you have proof that a given macro is being imported, but then proof it's *not* being imported. Given the example above, that's just not possible. The only thing I can think of that's *vaguely* like what you describe is ["Some More Gotchas" from APItMiR](https://danielkeep.github.io/practical-intro-to-macros.html#some-more-gotchas); specifically, the part on "Macros are (sometimes) lexically-scoped." If that isn't your problem, then I have no idea what is. – DK. Sep 27 '15 at 04:18
  • @DK. - I realize it doesn't make sense, which is why I posted my question. It seems ridiculous to me that after the compiler expands the macro, it suddenly decides that it can't expand the macro. As far as an MCVE goes, I'm not sure what more to include. I can't demonstrate this on the Rust playground since it necessarily uses multiple files. I will try adding more explicit code to the main.rs example though. – zrneely Sep 27 '15 at 13:07

1 Answers1

3

This example reproduces your problem:

Cargo.toml

[package]
name = "mac"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]

[dependencies]
lazy_static = "0.1.14"

src/lib.rs

#[macro_use]
extern crate lazy_static;

lazy_static! {
    pub static ref LIBRARY_VERSION: u8 = 1;
}

pub fn adder(a: u8, b: u8) -> u8 { a + b }

src/main.rs

extern crate mac;

lazy_static! {
    static ref EXECUTABLE_VERSION: u8 = 1;
}

fn main() {
    println!("Adder version {} (lib version {})", *EXECUTABLE_VERSION, *mac::LIBRARY_VERSION);
    println!("Result: {}", mac::adder(1, 2));
}

The problem is that macro inclusions are not transitive across crates. Including them in your library file doesn't make them available in any downstream crate that uses your library. That would blow any kind of selective usage completely out of the water; think how many items you would have in a project with 20 dependencies (that each themselves can have dependencies)!

You need to explicitly include the macros in your executable file as well, as it's a different crate:

#[macro_use]
extern crate lazy_static;
// ... rest of above src/main.rs
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366