Rust: decl_macro:导入在跨板条箱调用中不起作用

创建于 2017-05-31  ·  3评论  ·  资料来源: rust-lang/rust

最小复制:

// 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

A-macros-2.0 C-bug

最有用的评论

很抱歉延迟到此为止。 已在 #46419 中修复。

所有3条评论

很抱歉延迟到此为止。 已在 #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...)将使这变得更容易。

此页面是否有帮助?
0 / 5 - 0 等级