Reprodução mínima:
// 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`.
Invocar a macro na mesma caixa que está definida funciona conforme o esperado.
cc @jseyfried
Desculpe pela demora em chegar a isso. Corrigido em # 46419.
Não sei se é o mesmo problema (e se o PR corrigiu), mas recebo o mesmo erro com proc_macro
.
Aqui está um exemplo mínimo para reproduzir esse problema.
É o mesmo problema?
Quando executo cargo build
, obtenho os seguintes erros:
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;
|
Existe alguma solução alternativa para esse problema?
Obrigada.
@antoyo Isso é uma consequência da higiene.
Como ::postgres::types::Type
está na definição da macro proc, ela resolve no escopo da definição da macro. Em particular, ele resolverá o mesmo, não importa onde a macro seja chamada.
Não há extern crate postgres;
na raiz da caixa proc-macro, então você obtém um erro de resolução. Apenas adicionar extern crate postgres;
à raiz da caixa proc-macro também não é suficiente, no entanto, uma vez que as dependências proc-macro são compiladas para a plataforma host (fase 0), não a plataforma alvo (fase 1) e assim a expansão não pode vê-los.
A solução aqui é adicionar dependências de destino às caixas proc-macro, conforme descrito em https://github.com/rust-lang/rust/issues/45934#issuecomment -344497531.
Por enquanto, você precisa colocar extern crate postgres;
na expansão da macro. Devido à higiene, isso não entrará em conflito com nada denominado postgres
no site de invocação, não afetará a resolução dos argumentos da macro, etc. Por exemplo:
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)
}
}
}
Alternativamente, você pode fazer ::postgres::types::Type
resolver no site da chamada (sem higiene) dando Span::call_site()
(tokens de quote!
têm Span::def_site()
por padrão). Em breve, spanned_quote!(span, tokens...)
tornará isso mais fácil.
Comentários muito úteis
Desculpe pela demora em chegar a isso. Corrigido em # 46419.