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 crate rootμ—λŠ” extern crate postgres; κ°€ μ—†μœΌλ―€λ‘œ ν•΄κ²° 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€. proc-macro crate root에 extern crate postgres; λ₯Ό μΆ”κ°€ν•˜λŠ” κ²ƒλ§ŒμœΌλ‘œλŠ” μΆ©λΆ„ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ proc-macro 쒅속성은 λŒ€μƒ ν”Œλž«νΌ(1단계)이 μ•„λ‹ˆλΌ 호슀트 ν”Œλž«νΌ(0단계)에 λŒ€ν•΄ μ»΄νŒŒμΌλ˜λ―€λ‘œ ν™•μž₯은 그듀을 λ³Ό 수 μ—†μŠ΅λ‹ˆλ‹€.

μ—¬κΈ°μ„œ 해결책은 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)
                    }
                }
            }

λ˜λŠ” Span::call_site() ( quote! 토큰은 기본적으둜 Span::def_site() λ₯Ό 가짐)λ₯Ό μ œκ³΅ν•˜μ—¬ ::postgres::types::Type 호좜 μ‚¬μ΄νŠΈμ—μ„œ (λΉ„μœ„μƒμ μœΌλ‘œ) ν•΄κ²°ν•˜λ„λ‘ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€. 곧 spanned_quote!(span, tokens...) 을(λ₯Ό) μ‚¬μš©ν•˜λ©΄ 이 μž‘μ—…μ΄ 더 μ‰¬μ›Œμ§‘λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰