如何在生锈的出口板条箱宏中引用板条箱中的功能?

时间:2014-09-18 08:31:00

标签: rust

我试图编写一些调试助手宏。所以我创建了一个箱子来容纳所有这些箱子,并使用phase(插件)从外部引用箱子:

#[cfg(test)]
#[phase(plugin)]
extern crate debugging;

成功将宏导出到包中。

但是,对于其中一些工具,我想从包中调用函数,例如:

#[macro_export]
macro_rules! trace(
  {$($arg:tt)*} => {
    {
      extern crate debug;
      let s = ::macros::logger(); // <---- This!
      let _ = s.write_line(format_args!(::std::fmt::format, $($arg)*).as_slice());
    }
  };
)

使用全局命名空间,即。如果将宏放入macros.rs并从包的箱子根目录导入,则:: macros :: logger可以正常工作。

然而,当宏必须从自己的包中调用一个调用时,我在这里尝试实现的是同样的事情。

如果宏扩展正确,我相信:

let s = ::crate_name::logger();

是这样做的方法,但是宏的箱子不能以这种方式通过名称引用自己。它会产生如下错误:

src/macros.rs:52:15: 52:20 error: failed to resolve. Maybe a missing `extern crate debugging`?
src/macros.rs:52       let s = ::debugging::logger();
                               ^~~~~
src/macros.rs:49:1: 56:2 note: in expansion of trace!
src/file.rs:26:11: 26:29 note: expansion site

......最后我们完全清楚我要做的事情:

crate debugging:
   lib.rs
     fn logger() 
   macros.rs
     macro_rules! trace(...) // <--- Trying to figure out what to put here...

crate foo:
   lib.rs
     #[phase(plugin)] extern crate debugging;
     fn test_thing() {
       trace!("{}", ...); // <--- So debugging::logger() is invoked here
     } 

那么,有没有办法从宏中做到这一点?

2 个答案:

答案 0 :(得分:2)

目前,正确的做法是使用类似的绝对路径,然后在原始包中进行一些重新导出,以便路径解析。

即。在lib.rs put

mod debugging {
    pub use logger;
}

将顶级函数logger重新导出为debugging::logger。正在进行的工作使这种方法变得更加合理,例如$crate扩展为宏来自的箱子的名称(当在外部使用时),或者什么都没有(在内部使用时);这不一定是最终设计,但它正在改进。

答案 1 :(得分:0)

对于其他发现此问题的人,值得注意的是,您无法使用标有阶段插件的箱子。要在本地导入符号(根据接受的答案),您需要执行以下操作:

#[cfg(test)]
mod debug {
  #[phase(plugin)]
  extern crate debugging;
  extern crate debugging;
  pub use self::debugging::debug;
}

请注意双外部包装箱调试,因为通常您不希望将语法扩展模块导出为代码的一部分。