在Rust中,人们经常看到以&str为参数的函数.

fn foo(bar: &str) {
    println!("{}", bar);
}

在调用这样的函数时,通过引用String作为参数来传递它是非常好的.

let bar = String::from("bar");
foo(&bar);

严格地说,传递的参数是&String,而函数期望的是&str,但Rust(正如人们所希望的)只是算出了它,一切都很好.但是,Match语句的情况并非如此.如果我try 在Match语句中使用与前面相同的bar变量,那么简单的用法将不会编译:

match &bar {
    "foo" => println!("foo"),
    "bar" => println!("bar"),
    _ => println!("Something else")
};

Rustc抱怨说,它原本预计会得到&str分,但实际上得到了&String分.问题和解决方案都是非常明显的:只要用.as_str()更明确地borrow bar就行了.但这让我想到了真正的问题:为什么会出现这种情况?

如果Rust可以计算出在函数参数的情况下&String可以很容易地转换为&str,为什么它不能对Match语句做同样的事情呢?这是类型系统限制的结果,还是更花哨的通过Match语句borrow 的隐藏的不安全因素?或者,这仅仅是生活质量的改善被融入到一些地方而不是其他地方的情况?我相信某个了解打字系统的人会有答案,但关于互联网上这种小怪异行为的信息似乎很少.

推荐答案

它不起作用的技术原因是,match名受检者不是coercion site分.函数参数,如您的foo(&bar)示例所示,可能是强制位置;由于Deref强制,它可以将&String作为&str传递.

它不是一个强制网站的一个可能的原因是,没有明确的类型应该被强迫.在您的示例中,您希望它是&str,因为它与字符串文字匹配,但以下情况如何:

match &string_to_inspect {
    "special" => println!("this is a special string"),
    other => println!("this is a string with capacity: {}", other.capacity()),
};

人们希望match表现得像&str一样,以匹配字面意思,但因为匹配的是&String,所以人们可能会认为other也是&String.如何才能同时满足这两方面的要求?下一个合乎逻辑的步骤是希望每个模式根据需要强制执行,这是人们非常希望的……但它打开了一整罐蠕虫,因为Deref是用户可定义的.更多信息,请参见铁 rust 语言团队的deref patterns.

Rust相关问答推荐

有没有方法处理rust中嵌套的ok_or()?

在Rust中赋值变量有运行时开销吗?

为什么实例方法可以像Rust中的静态方法一样被调用?

默认特征实现中的生命周期问题

使用极点数据帧时,找不到枚举结果的方法lazy()

如何高效地将 struct 向量中的字段收集到单独的数组中

用于判断整数块是否连续的SIMD算法.

为什么 GAT、生命周期和异步的这种组合需要 `T: 'static`?

为什么 Rust 创建的 f32 小于 f32::MIN_POSITIVE?

为什么 js_sys Promise::new 需要 FnMut?

面临意外的未对齐指针取消引用:地址必须是 0x8 的倍数,但为 0x__错误

为什么我的trait 对象类型不匹配?

如何将 C++ 程序链接到 Rust 程序,然后将该 Rust 程序链接回 C++ 程序? (cpp -> rust -> cpp)

如何从 x86_64 Mac 构建 M1 Mac?

如果不满足条件,如何在 Rust 中引发错误

在 Rust 中,Weak 如何知道内部值何时被删除?

当我在 struct 中存储异步函数时,为什么它需要生命周期

如何为枚举中的单个或多个值返回迭代器

如何迭代调用可能会失败的函数?操作员?

基于名称是否存在的条件编译