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`.

定義されているのと同じクレートでマクロを呼び出すと、期待どおりに機能します。

cc @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クレートルートにextern crate postgres;がないため、解決エラーが発生します。 ただし、proc-macroの依存関係はターゲットプラットフォーム(フェーズ1)ではなくホストプラットフォーム(フェーズ0)用にコンパイルされるため、proc-macroクレートルートにextern crate postgres;を追加するだけでは不十分です。拡張はそれらを見ることができません。

ここでの解決策は、 https: //github.com/rust-lang/rust/issues/45934#issuecomment -344497531で説明されているように、ターゲットの依存関係をproc-macroクレートに追加することです。

今のところ、マクロ展開に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)
                    }
                }
            }

また、あなたが作ることができます::postgres::types::Typeそれを与えることによって、呼び出しサイト(unhygienically)で決意をSpan::call_site() (トークンからquote!持っているSpan::def_site()デフォルトで)。 間もなく、 spanned_quote!(span, tokens...)これが簡単になります。

このページは役に立ちましたか?
0 / 5 - 0 評価