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 引用则不满足。
备注:内容仅供参考。
