types - 为什么由于缺少类型注释而收到错误 "trait bound FromStr is not satisfied"?

标签 types rust pattern-matching traits

我遇到了一个编译错误,似乎突出显示了我对类型系统不了解的内容。
我想将字符串转换为整数,如果字符串不是有效整数,则带有自定义 panic 消息。我做一个matchResultparse() 返回:

fn main() {
    let x = match "23".parse() {
        Ok(int) => int,
        Err(_) => panic!("Not an integer!"),
    };
    println!("x plus 1 is {}", x+1);
}
(如果这真的是我在程序中所做的全部,我会使用 expect() ,但在实际程序中还有更多内容。)
我希望输出 24编译并运行时。相反,会出现以下编译器错误:
error[E0277]: the trait bound `(): std::str::FromStr` is not satisfied
 --> main.rs:2:24
  |
2 |     let x = match "23".parse() {
  |                        ^^^^^ the trait `std::str::FromStr` is not implemented for `()`
问题似乎是 Rust 不知道我要解析的类型,这可能是一个问题是有道理的。如果我将第 2 行更改为以下内容,错误就会消失:
    let x: i32 = match "23".parse() {
为什么我收到此错误消息,而不是指示需要类型注释?该消息似乎在提示错误臂没有返回任何东西(或者更准确地说,它返回的东西 - 即什么都没有 - 没有实现 FromStr 特征),但对我来说没有任何意义, 调用 panic! 后,匹配的那个分支的输出类型可能会产生任何影响——程序可能会展开堆栈并在该点立即终止,因此类型安全似乎无关紧要!
一个提示是,如果不是调用 panic! ,我只返回一个整数(例如 Err(_) => 0 ),代码编译良好(并按预期工作)。似乎在这种情况下,Rust 正确地将类型推断为 i32第一次并且不会运行导致困惑错误的任何代码路径。

最佳答案

The message appears to be complaining that the error arm does not return anything (or more precisely, that what it returns -- namely nothing -- doesn't implement the FromStr trait).


其实你第一次是对的。错误臂永远不会返回。 panic! 的返回类型字面意思是 never type ( ! ),它不同于 unit type ( () )确实返回,尽管它返回的是“无”。
专业提示:永不返回的函数称为发散函数。

it doesn't make any sense to me that, after calling panic!, the type of the output of that arm of the match could have any effect whatsoever.


它没有。 never 类型对类型推断没有影响,可以用来代替任何其他类型。例如,此程序编译时没有任何错误或警告:
#![allow(unreachable_code)]

fn main() {
    let _x: () = panic!();
    let _y: i32 = panic!();
    let _z: &dyn ToString = panic!();
}
但是,我们使用上面的一堆类型注释来操作返回类型,而不是任何类型提示,Rust 似乎解决了默认值 ()。对于返回 ! 的表达式如您的示例的简化版本所示:
#![allow(unreachable_code)]

fn main() {
    let x = panic!();
    x + 5;
}
哪个抛出:
error[E0277]: cannot add `i32` to `()`
  --> src/main.rs:15:7
   |
15 |     x + 5;
   |       ^ no implementation for `() + i32`
   |
   = help: the trait `std::ops::Add<i32>` is not implemented for `()`
这似乎是一个合理的选择,因为空表达式(例如空 block )评估为单元类型。
简而言之:当您将发散函数作为表达式的最后一条语句并且不使用任何类型注释时,Rust 会推断表达式的返回类型为 () .这就是为什么推断您的错误臂返回 ()以及为什么你会得到 FromStr not implemented for ()错误。

关于types - 为什么由于缺少类型注释而收到错误 "trait bound FromStr is not satisfied"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62628980/

相关文章:

java - 性能偏执狂 : how much expensive are Float. parseFloat(String), Integer.parseInt(String)?

javascript - JScript/WMI - 如何检查项目的类/类型?

rust - "the immutable borrow prevents mutable borrows"当使用 rust-sdl2 抽取事件时

bash - 如何从一组文件中删除与某个模式匹配的所有行?

java - 如何从这样的字符串中提取 double

scala - Scala 中的高级类型是什么?

go - 为什么在 Go 类型开关中声明一个单独的变量?

floating-point - 如何处理 Rust 中不精确的浮点运算结果?

rust - 从 if 语句中返回值时出现 "mismatched types"错误

regex - 正则表达式验证采用类似日期的格式