代码:
struct Foo;
impl Into<u32> for Foo {
fn into(self) -> u32 {
1
}
}
fn main() {
let foo = Foo;
let bar: u32 = foo.into() * 1u32;
}
我收到错误信息。
error[E0283]: type annotations needed
--> src/main.rs:11:24
|
11 | let bar: u32 = foo.into() * 1u32;
| ^^^^
|
note: multiple `impl`s satisfying `Foo: Into<_>` found
--> src/main.rs:3:1
|
3 | impl Into<u32> for Foo {
| ^^^^^^^^^^^^^^^^^^^^^^
= note: and another `impl` found in the `core` crate:
- impl<T, U> Into<U> for T
where U: From<T>;
help: try using a fully qualified path to specify the expected types
|
11 | let bar: u32 = <Foo as Into<T>>::into(foo) * 1u32;
| +++++++++++++++++++++++ ~
For more information about this error, try `rustc --explain E0283`.
error: could not compile `hello` (bin "hello") due to 1 previous error
我无法理解该错误信息。
这个错误是什么意思?这是否意味着语言核心也Into
为我实现了特征struct Foo
,而编译器不知道该使用哪一个?为什么核心包Into
为我实现了?我在哪里可以了解有关此主题的更多信息?
这个板条箱是什么
core
?不。语言(实际上是编译器)仅实现“自动特征”(例如
Send
,Sync
等等)。但是标准库包含一堆通用特征实现。编译器错误说明了
core
板条箱的情况。Rust 的标准库分为 3 个板条箱。core
(无依赖性、最低级别的构建块)、alloc
(涉及分配的所有内容)和std
(与操作系统交互、从板条箱重新导出项目)。因此,编译器实际上会告诉您标准库中存在一些实现(其中的一部分)。core
alloc
core
编译器为什么会报错?
特征
From
和Into
具有反射性。这意味着标准库中存在以下总体实现:这两项全面实施都意味着
impl<T> Into<T> for T
。这意味着使用这些特征进行类型推断是比较棘手的。一般来说你不能这样写
因为编译器无法推断左侧模式和右侧表达式的类型。你可能认为通过在 上写类型注释来描述其类型
bar
:但是由于你使用的是
*
运算符,编译器实际上调用的是std::ops::Mul
特征的某些特定实现。因此上面这行代码被翻译成如下内容:编译器尝试推断
<Some unknown type>
,但它唯一能推断出的是,这是一种表达式类型foo.into()
。所以我们又回到let x: _ = foo.into()
问题上了。请注意,如果我们改变乘以的参数的顺序
let bar: u32 = 1u32 * foo.into();
,那么编译器将产生额外的错误,这进一步提示了问题:如何修复这个错误?
您必须按照编译器的要求进行操作。指定它无法推断的类型。例如,使用完全限定语法:
或者通过定义中间变量: