[英]Why do I get the error “trait bound FromStr is not satisfied” because of a missing type annotation?
I encountered a compile error that seems to be highlighting something I don't understand about the type system.我遇到了一个编译错误,似乎突出显示了我对类型系统不了解的内容。
I want to convert a string to an integer, with a custom panic message if the string isn't a valid integer.如果字符串不是有效的 integer,我想将字符串转换为 integer,并带有自定义紧急消息。 I do a
match
on the Result
that's returned by parse()
:我对
parse()
返回的Result
进行match
:
fn main() {
let x = match "23".parse() {
Ok(int) => int,
Err(_) => panic!("Not an integer!"),
};
println!("x plus 1 is {}", x+1);
}
(If this were really all I was doing in my program, I would just use expect()
, but there's more to it in the real program.) (如果这真的是我在我的程序中所做的一切,我只会使用
expect()
,但在真正的程序中还有更多。)
I would expect the output 24
when compiled and run.我希望 output
24
编译和运行时。 Instead, the following compiler error appears:相反,会出现以下编译器错误:
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 `()`
The issue seems to be that Rust doesn't know what type I'm trying to parse to, and it makes sense this could be a problem.问题似乎是 Rust 不知道我要解析的类型,这可能是一个问题。 If I change line 2 to the following, the error goes away:
如果我将第 2 行更改为以下内容,错误就会消失:
let x: i32 = match "23".parse() {
Why did I get this error message, instead of one indicating that a type annotation was required?为什么我收到此错误消息,而不是指示需要类型注释? 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), but it does not make any sense to me that, after calling panic!
该消息似乎在抱怨错误 arm 没有返回任何内容(或者更准确地说,它返回的内容 - 即什么都没有 - 没有实现
FromStr
特征),但对我来说没有任何意义,之后呼唤panic!
, the type of the output of that arm of the match could have any effect whatsoever -- the program is presumably going to unwind the stack and terminate immediately at that point, so type safety would seem irrelevant! ,匹配的 arm 的 output 的类型可能会产生任何影响——该程序可能会展开堆栈并在该点立即终止,因此类型安全似乎无关紧要!
One hint is that if instead of calling panic!
一个提示是 if 而不是调用
panic!
, I simply return an integer (eg, Err(_) => 0
), the code compiles fine (and works as expected). ,我只是返回一个 integer (例如,
Err(_) => 0
),代码编译良好(并按预期工作)。 It seems that in this case, Rust correctly infers the type to be i32
the first time around and doesn't run down whatever code path is leading to the confusing error.在这种情况下,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).该消息似乎在抱怨错误 arm 没有返回任何内容(或者更准确地说,它返回的内容 - 即什么都没有 - 没有实现
FromStr
特征)。
Actually you were right the first time.其实你第一次是对的。 The error arm never returns.
错误 arm 永远不会返回。 The return type of
panic!
panic!
is literally called the never type ( !
) and it's different from the unit type ( ()
) which does return, although what it returns is "nothing".字面上称为永不类型(
!
),它与确实返回的单元类型( ()
)不同,尽管它返回的是“无”。
Pro-tip: functions which never return are called divergent functions.专业提示:永不返回的函数称为发散函数。
it doesn't make any sense to me that, after calling
panic!
在调用
panic!
, the type of the output of that arm of the match could have any effect whatsoever.,匹配的 arm 的 output 的类型可能会产生任何影响。
It doesn't.它没有。 The never type has no influence on type inference and can be used in place of any other type.
never 类型对类型推断没有影响,可以用来代替任何其他类型。 For example, this program compiles without any errors or warnings:
例如,此程序编译时没有任何错误或警告:
#![allow(unreachable_code)]
fn main() {
let _x: () = panic!();
let _y: i32 = panic!();
let _z: &dyn ToString = panic!();
}
However, we're using a bunch of type annotations above to manipulate the return type, in lieu of any type hints whatsoever Rust seems to settle on the default of ()
for expressions that return !
但是,我们使用上面的一堆类型注释来操作返回类型,而不是任何类型提示,Rust 似乎对返回的表达式默认使用
()
!
as shown by this simplified version of your example:如您的示例的简化版本所示:
#![allow(unreachable_code)]
fn main() {
let x = panic!();
x + 5;
}
Which throws:哪个抛出:
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 `()`
This seems like a reasonable choice given that empty expressions, such as an empty block, evaluate to the unit type.这似乎是一个合理的选择,因为空表达式(例如空块)评估为单元类型。
In short: when you put a divergent function as the final statement in an expression and don't use any type annotations Rust infers the expression's return type to be ()
.简而言之:当您将发散的 function 作为表达式中的最终语句并且不使用任何类型注释时,Rust 会推断表达式的返回类型为
()
。 This is why your error arm is inferred to return ()
and why you get the FromStr not implemented for ()
error.这就是为什么您的错误 arm 被推断为 return
()
以及为什么您得到FromStr not implemented for ()
错误的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.