在 Rust 的过程宏中使用 $crate?

30

我知道 $crate 变量是什么,但据我所知,它不能在过程宏中使用。有没有其他方法可以实现类似的效果?

我有一个示例,大致需要我使用 quote 和 Rust 夜版写出类似以下的内容。

quote!(
     struct Foo {
        bar: [SomeTrait;#len]
     }
)

我需要确保SomeTrait在范围内(#len引用了片段范围外的整数)。

我正在使用基于quotesyn的过程宏2.0,因为proc-macro-hack对我没有起作用。这是我尝试推广的示例


1
你的过程宏确实生成了一个结构体而不是一个 impl 块吗?由于某些愚蠢的原因,对于生成结构体的宏来说,最可靠的方法比生成 impl 的宏要复杂得多。 - dtolnay
这是用于 proc_macro_derive 宏,还是其他类型的过程宏? - dtolnay
[SomeTrait; #len] 这样的写法是不可行的,因为 [T; n] 要求 T: Sized。请参考 https://play.rust-lang.org/?gist=bb33e5ba42a7e64af998b014483329f0。您能澄清一下预期的结果吗? - dtolnay
@dtolnay: 1.它生成了一个结构体和一个 impl 块。 2.这是针对Nightly宏2.0的; 3.类似于 https://play.rust-lang.org/?gist=415163c29391484ada4c876553ebf23f&version=stable&backtrace=0 (我需要过程宏,因为我想以特定的方式解析第一个参数) - Daniel Fath
@dtolnay 更新了带有澄清的问题。 - Daniel Fath
5个回答

10

4

2
在2015版(经典Rust)中,您可以这样做(但是这很糟糕):
  • 在宏中使用::defining_crate::SomeTrait
  • 在依赖于defining_crate的第三方crate中,上述方法可以正常工作
  • defining_crate内部,在根目录下添加一个模块:

    mod defining_crate { pub use super::*; }

在2018版中需要更多的hacky解决方案(请参见this issue),不过#55275可能会给我们提供一个简单的解决方法。

1
您可以将proc-macro包装在声明性宏内,并将$crate标识符传递给您的proc-macro以进行重用(例如,请参见此提交)。它将创建一个带有特殊$crate标识符的proc_macro :: Ident值。
请注意,您无法手动创建此类标识符,因为$通常无效于标识符内部。

我相信这对属性宏无效。 - Enrico Borba

-1

从 Rust 1.45 开始,你可以使用 Span::mixed_site 作为Ident的范围来直接使用 $crate 并避免与本地变量冲突。

quote_spanned!(Span::mixed_site()=>
     struct Foo {
        bar: [$crate::SomeTrait; #len]
     }
)

1
嘿,我尝试了这种方法,但对我没有用。请参见我的问题 - Einliterflasche

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接