Невозможно использовать макросы, импортированные в библиотеку в исполняемом файле, который использует эту библиотеку
У меня много проблем с получением макросов из другого ящика для работы в 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