You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Rust声明式宏b!支持结构体字段文档悬停显示?

如何让声明式宏b!支持字段文档悬停?

我有两个用于构建同一Hello结构体的声明式宏:a!使用通用标识符匹配字段名,b!匹配特定的name字段。但在VS Code中,只有a!能在宏调用内的name上悬停显示字段的文档注释。请问如何让b!也实现该功能?

代码示例

struct Hello {
    /// Name docs
    name: String
}

macro_rules! a {
    ($name:ident: $value:expr) => {
        Hello { $name: $value }
    };
}

macro_rules! b {
    (name: $expr:expr) => {
        Hello { name: $expr }
    };
}

fn main() {
    let hello_alice = a!(name: String::from("Alice"));
    let hello_bob = b!(name: String::from("Bob"));
}

问题原因

b!的匹配器里的name是硬编码的字面量,Rust语言服务(如Rust Analyzer)无法将其与Hello结构体的name字段建立关联。而a!使用了$name:ident标识符捕获,语言服务能识别出这个捕获的标识符对应结构体的字段,因此可以正常显示文档注释。

解决方案

修改b!的定义,将匹配器中的name改为标识符捕获,并添加编译时校验确保只能传入name字段。这样既保留了只匹配name的逻辑,又能让语言服务关联到结构体字段,实现悬停显示文档:

struct Hello {
    /// Name docs
    name: String
}

macro_rules! a {
    ($name:ident: $value:expr) => {
        Hello { $name: $value }
    };
}

macro_rules! b {
    ($name:ident: $expr:expr) => {
        // 编译时校验:确保传入的字段名是name
        const _: () = assert!(stringify!($name) == "name");
        Hello { $name: $expr }
    };
}

fn main() {
    let hello_alice = a!(name: String::from("Alice"));
    let hello_bob = b!(name: String::from("Bob"));
    // 传入非name字段会触发编译错误,符合需求
    // let hello_error = b!(age: String::from("18"));
}

如果不需要严格限制只能传入name字段,只是想让name的悬停生效,也可以直接将b!改为通用标识符匹配形式(和a!一致),这样所有字段的悬停都能正常工作。

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 16:07:44