PAYATHON 2026

Rust 中对 &mut String 调用 type_id() 为何要求 'static?

数据阿明

结论

问题出在 type_id() 的方法解析上:tt.type_id() 在两种写法中可能选中不同的 Any 实现。不可变引用会解析到 String 的 Any::type_id;可变引用则可能解析到 &mut String 的实现。Any 只为满足 'static 的类型实现,而局部借用类型 &mut String 不满足这一约束,所以编译器会报告 t 必须借用到 'static。

&mut 借用本身不需要满足 'static。这里触发 Any 的 'static 限制,是因为方法解析选中了引用类型。

两种写法为何结果不同

Any::type_id 的接收者是 &self。调用方法时,Rust 会依次尝试不同的接收者类型:

  • 对 tt: &String,接收者可以匹配 String 的 &self,因此取得 String 的 TypeId。
  • 对 tt: &mut String,可变引用不能按相同方式匹配 String 的不可变接收者。方法解析会继续尝试,并可能匹配 Self = &mut String 的 Any::type_id。这个引用类型带有局部借用生命周期,不满足 Any 的 'static 要求,因此编译失败。

因此,错误信息中的“argument requires that t is borrowed for 'static”来自所选方法实现的类型约束,并不表示普通的可变借用必须持续到程序结束。

显式对被引用的值调用

显式解引用后再调用 type_id(),可以让方法针对 String 解析。也可以直接调用 trait 方法,避免方法解析歧义:

use std::any::{Any, TypeId};

fn main() {
    let mut t = String::from("Hello, world!");
    let tt = &mut t;

    let id = Any::type_id(&*tt);
    assert_eq!(id, TypeId::of::<String>());
}

这里的 &*tt 会对 String 创建一个不可变重借用,因此 Any::type_id 作用于 String,而非 &mut String。也可以写成 (*tt).type_id()。Any::type_id(&*tt) 更清楚地表明,查询的是被引用值的类型。

注意事项

Any 的 'static 约束要求类型不包含非 'static 的借用,并不要求 String 值一直存活到程序结束。这个例子中的 String 类型满足该约束,因此可以查询它的 TypeId;局部的 &mut String 引用则不满足。

备注:内容仅供参考。