Невозможно использовать макросы, импортированные в библиотеку в исполняемом файле, который использует эту библиотеку

У меня много проблем с получением макросов из другого ящика для работы в Rust. Мой файл lib.rs выглядит так:

#[macro_use]
extern crate session_types;

mod main;

А вот упрощенная часть моего main.rs, демонстрирующая правильное использование offer! макрос:

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()
            };
        }
    }
}

Я знаю, что компилятор может расширяться offer! потому что я отлаживал код в блоках внутри этого макроса и получал предупреждения о неиспользуемых переменных в этом макросе, которые выглядят так:

<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! {

который, очевидно, включает в себя часть макроса. Тем не менее, я получаю ошибки компиляции, говоря, что в строках, которые они используют, макрос offer! не определено

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,

Примечание: это происходит в ночной ветке компилятора.

1 ответ

Решение

Этот пример воспроизводит вашу проблему:

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));
}

Проблема заключается в том, что макро-включения не являются транзитивными через ящики. Включение их в файл библиотеки не делает их доступными ни в одном из последующих ящиков, которые используют вашу библиотеку. Это полностью выбило бы из воды любое избирательное использование; подумайте, сколько элементов у вас будет в проекте с 20 зависимостями (каждый из которых может иметь зависимости)!

Вам также нужно явно включить макросы в ваш исполняемый файл, так как это другой ящик:

#[macro_use]
extern crate lazy_static;
// ... rest of above src/main.rs
Другие вопросы по тегам