如何内联重新曝光整个板条箱

How to reexpose an entire crate inline

我有一个 proc-macro 也公开了一些类型,所以我使用以下 crate 结构:

我 运行 遇到的问题是重新导出 foo_core 会改变它的路径。

foo_macro 生成的代码大致如下:

struct Bar;

impl ::foo_core::FooTrait for Bar {
  // ...
}

我在 foo_macro 中有一堆 trybuild 测试通过了,因为 foo_core 是一个可用的箱子。

问题是当我尝试在 foo(或仅依赖于 foo 的 crate 中编写测试时,我收到错误消息,告诉我找不到 crate foo_core.

这对我来说有些道理; foo 的消费者没有明确依赖 foo_core,但如果我的板条箱的用户不必添加 foofoo_core(以及确保版本匹配),相反,我希望他们能够添加 foo 并且它会起作用。

目前,我可以通过 foo::foo_core::FooTrait 访问 foo_core,但显然这与我的宏生成代码 (::foo_core::FooTrait) 的方式不同。有没有办法让 foo 重新导出整个 foo_core crate?

如果这不可能,那么处理此模式的最佳方法是什么?我能以某种方式让 foo_macro 根据定义它的板条箱改变它的行为吗?或者我应该将所有测试移至 foo 而不是 foo_macro

这个问题的答案提到了这个问题,但只是说“你必须使用完全合格的名称”,但我的理解是这就是领先的 ::路径意味着。

这似乎是一种相对常见的模式,所以我希望有一个很好的解决方案。

在您的 foo 箱子中,您可以完全重新导出 foo_core

  • pub extern crate foo_core;
  • pub use foo_core;

使用这些语句中的任何一个,当 Cargo.toml[dependencies] 部分中只有 foo 时,可以通过 foo::foo_core:: 访问所有 foo_core .然后你的 proc 宏会发出 ::foo::foo_core:: 路径。这当然要求用户不要直接使用foo_macrofoo_core。但这很常见:通常,人们不应该直接使用宏 crate,而只能使用“顶级 crate”。

这是一种常见的模式,不仅适用于您自己的板条箱。例如,在我的一个库中,我的 proc 宏生成对 serde 函数(不是我的库)的调用。所以我 pub use serde; 在我的箱子里,这样我图书馆的用户就不必直接依赖 serde