最小复制:
// src/lib.rs
#![feature(decl_macro)]
pub macro use_fmt {
() => {
use std::fmt;
}
}
// examples/test.rs
#![feature(use_extern_macros)]
extern crate macro_test;
use macro_test::use_fmt;
use_fmt!();
fn main() {}
The error:
$ cargo build --example test
Compiling macro-test v0.1.0 (file:///.../macro-test)
error[E0432]: unresolved import `std::fmt`
--> examples/test.rs:7:1
|
7 | use_fmt!();
| ^^^^^^^^^^^ Could not find `std` in `{{root}}`
|
= note: this error originates in a macro outside of the current crate
error: aborting due to previous error(s)
error: Could not compile `macro-test`.
在定义的同一个 crate 中调用宏按预期工作。
抄送@jseyfried
很抱歉延迟到此为止。 已在 #46419 中修复。
我不知道这是否是相同的问题(以及 PR 是否修复了它),但我在proc_macro
遇到了同样的错误。
这是重现此问题的最小示例。
这是同样的问题吗?
当我运行cargo build
,出现以下错误:
error[E0433]: failed to resolve. Could not find `postgres` in `{{root}}`
--> src/lib.rs:9:17
|
9 | #[derive(Debug, SqlTable)]
| ^^^^^^^^ Could not find `postgres` in `{{root}}`
error[E0433]: failed to resolve. Could not find `std` in `{{root}}`
--> src/lib.rs:9:17
|
9 | #[derive(Debug, SqlTable)]
| ^^^^^^^^ Could not find `std` in `{{root}}`
error[E0412]: cannot find type `Table` in this scope
--> src/lib.rs:9:17
|
9 | #[derive(Debug, SqlTable)]
| ^^^^^^^^ not found in this scope
help: possible candidate is found in another module, you can import it into scope
|
3 | use Table;
|
这个问题有什么解决方法吗?
谢谢你。
@antoyo这是卫生的结果。
由于::postgres::types::Type
在 proc-macro 定义中,它在宏定义的范围内解析。 特别是,无论在哪里调用宏,它都会解决相同的问题。
proc-macro crate 根目录中没有extern crate postgres;
,因此会出现解析错误。 仅仅将extern crate postgres;
到 proc-macro crate root 也是不够的,但是,因为 proc-macro 依赖项是为主机平台(阶段 0)而不是目标平台(阶段 1)编译的,所以扩展看不到它们。
这里的解决方案是将目标依赖项添加到 proc-macro crates,如https://github.com/rust-lang/rust/issues/45934#issuecomment -344497531 中所述。
现在,您需要在宏扩展中放入extern crate postgres;
。 由于卫生,这不会与调用站点上名为postgres
任何内容冲突,不会影响宏参数的解析等。例如:
quote! {
extern crate std;
extern crate postgres;
use std::io::Write;
use postgres::types::{IsNull, ToSql, Type};
impl ToSql for #table_ident {
fn to_sql<W: Write + ?Sized>(&self, ty: &Type, out: &mut W) -> postgres::Result<IsNull> {
self.#primary_key_ident.to_sql(ty, out)
}
fn accepts(ty: &Type) -> bool {
match *ty {
Type::Int4 => true,
_ => false,
}
}
fn to_sql_checked(&self, ty: &Type, out: &mut Write) -> postgres::Result<IsNull> {
if !<Self as ToSql>::accepts(ty) {
return Err(postgres::error::Error::WrongType(ty.clone()));
}
self.to_sql(ty, out)
}
}
}
或者,您可以通过给Span::call_site()
(来自quote!
令牌默认Span::def_site()
)在呼叫站点(不卫生地)使::postgres::types::Type
解析。 很快, spanned_quote!(span, tokens...)
将使这变得更容易。
最有用的评论
很抱歉延迟到此为止。 已在 #46419 中修复。