为什么我会因为缺少类型注释而收到错误 "trait bound FromStr is not satisfied"?
Why do I get the error "trait bound FromStr is not satisfied" because of a missing type annotation?
我遇到了一个编译错误,似乎突出显示了我对类型系统不了解的地方。
我想将字符串转换为整数,如果字符串不是有效整数,则使用自定义紧急消息。我在由 parse()
:
编辑的 return 上做了一个 match
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() {
为什么我收到 this 错误消息,而不是指示需要类型注释的错误消息?该消息似乎在抱怨错误臂没有 return 任何东西(或者更准确地说,它 returns —— 即什么都没有 —— 没有实现 FromStr
特性) ,但对我来说没有任何意义,在调用 panic!
之后,匹配的那个分支的输出类型可能会产生任何影响——程序可能会展开堆栈并立即终止在这一点上,类型安全似乎无关紧要!
一个提示是,如果我不调用 panic!
,而是简单地 return 一个整数(例如,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).
其实你第一次是对的。错误臂永远不会 returns。 panic!
的 return 类型字面上称为 never type (!
) and it's different from the unit type (()
),它执行 return,尽管它 return 是“无” .
专业提示:从不 return 的函数称为发散函数。
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!();
}
然而,我们正在使用上面的一堆类型注释来操作 return 类型,以代替任何类型提示,无论 Rust 似乎对表达式的默认设置 ()
return !
如示例的简化版本所示:
#![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 `()`
考虑到空表达式(例如空块)的计算结果为单位类型,这似乎是一个合理的选择。
简而言之:当您将发散函数作为表达式的最终语句并且不使用任何类型注释时,Rust 会推断表达式的 return 类型为 ()
。这就是为什么你的错误臂被推断为 return ()
以及你得到 FromStr not implemented for ()
错误的原因。
我遇到了一个编译错误,似乎突出显示了我对类型系统不了解的地方。
我想将字符串转换为整数,如果字符串不是有效整数,则使用自定义紧急消息。我在由 parse()
:
match
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() {
为什么我收到 this 错误消息,而不是指示需要类型注释的错误消息?该消息似乎在抱怨错误臂没有 return 任何东西(或者更准确地说,它 returns —— 即什么都没有 —— 没有实现 FromStr
特性) ,但对我来说没有任何意义,在调用 panic!
之后,匹配的那个分支的输出类型可能会产生任何影响——程序可能会展开堆栈并立即终止在这一点上,类型安全似乎无关紧要!
一个提示是,如果我不调用 panic!
,而是简单地 return 一个整数(例如,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).
其实你第一次是对的。错误臂永远不会 returns。 panic!
的 return 类型字面上称为 never type (!
) and it's different from the unit type (()
),它执行 return,尽管它 return 是“无” .
专业提示:从不 return 的函数称为发散函数。
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!();
}
然而,我们正在使用上面的一堆类型注释来操作 return 类型,以代替任何类型提示,无论 Rust 似乎对表达式的默认设置 ()
return !
如示例的简化版本所示:
#![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 `()`
考虑到空表达式(例如空块)的计算结果为单位类型,这似乎是一个合理的选择。
简而言之:当您将发散函数作为表达式的最终语句并且不使用任何类型注释时,Rust 会推断表达式的 return 类型为 ()
。这就是为什么你的错误臂被推断为 return ()
以及你得到 FromStr not implemented for ()
错误的原因。