Rust中match匹配&str引用报错,为何另一处比较正常?
Rust中两次&str比较行为差异的原因
问题场景
我编写了一个简化的Rust函数,用于检查url::Host是否为本地主机:
fn is_localhost(host: &Host<&str>) -> bool { match host { Host::Domain(d) => { d == "localhost" || d.ends_with(".localhost") }, Host::Ipv4(a) => a.is_loopback(), Host::Ipv6(a) => a.is_loopback(), } }
执行cargo check时出现编译错误:
d == "localhost" || d.ends_with(".localhost") ^^ no implementation for `&str == str`
通过解引用d(*d == "localhost")可解决该问题。但在另一处代码中:
if url.scheme() == "https" { return true; }
url.scheme()返回&str,与"https"(&'static str)比较却能正常运行。为何两种场景下的&str引用比较结果不同?
核心原因
差异的本质是两处代码中参与比较的引用层数不同:
Host::Domain(d)的引用类型
当函数参数是&Host<&str>时,Host::Domain变体中的d是&&str——对&str的二次引用。这是因为url库的Host枚举定义中,Domain存储的是泛型参数T,而这里的T是&str,所以最终d的类型是&T即&&str。当你用
d == "localhost"时,字符串字面量"localhost"会被自动解引用为str(Rust的Deref强制转换特性),此时比较的是&&str和str,而标准库没有实现这两种类型的PartialEq,因此编译报错。url.scheme()的返回类型url.scheme()直接返回&str(一次引用),而"https"是&'static str——本质上也是&str,只是生命周期为静态。标准库实现了不同生命周期&str之间的PartialEq,所以这种比较可以直接通过编译。
验证与替代方案
你可以通过打印类型确认d的实际类型:
use url::Host; fn is_localhost(host: &Host<&str>) -> bool { match host { Host::Domain(d) => { println!("d的类型:{}", std::any::type_name::<typeof(d)>()); *d == "localhost" || d.ends_with(".localhost") }, Host::Ipv4(a) => a.is_loopback(), Host::Ipv6(a) => a.is_loopback(), } }
除了解引用d,还有两种替代解决方式:
- 将字符串字面量也转为二次引用:
d == &"localhost",让两边类型统一为&&str - 调整函数参数为
Host<&str>(去掉外层引用),此时d的类型变为&str,可直接和"localhost"比较
内容的提问来源于stack exchange,提问作者jtepe
相关产品推荐
相关产品推荐

