为何rustc无法推断引用调用into方法的类型?加括号可正常编译?
Rust类型推断疑问:
*i_ref.into()编译失败,(*i_ref).into()却正常? 先看你的代码:
struct Number { n: i32, } impl From<i32> for Number { fn from(n: i32) -> Self { Self { n } } } pub fn main() { let i = 5; let i_ref = &i; let m: Number = *i_ref.into(); // 编译报错 // let m: Number = (*i_ref).into(); // 正常编译 println!("{}", m.n); }
编译时的错误信息:
Compiling playground v0.0.1 (/playground) error[E0282]: type annotations needed --> src/main.rs:14:28 | 14 | let m: Number = *i_ref.into(); | ^^^^ | help: try using a fully qualified path to specify the expected types | 14 | let m: Number = *<&{integer} as Into<T>>::into(i_ref); | ++++++++++++++++++++++++++++++ ~
核心原因:运算符优先级+类型推断逻辑
首先纠正优先级误解:方法调用(
.xxx())的优先级比解引用运算符*更高,所以两行代码的执行顺序完全不同:*i_ref.into():先执行i_ref.into(),再对返回值做解引用(*i_ref).into():先解引用i_ref得到i32,再执行.into()
类型推断的差异:
- 对于
i_ref.into():i_ref的类型是&i32,标准库中&i32可以对应多种Into的目标类型(比如自身&i32、值类型i32等)。虽然最终要得到Number,但&i32并没有直接实现Into<Number>(我们只给i32实现了Into<Number>),同时解引用*可以作用于任意引用类型,编译器无法从最终的Number类型倒推.into()应该返回什么类型,因此报错要求补充类型注解。 - 对于
(*i_ref).into():解引用后得到明确的i32类型,而Rust会自动为实现了From<T>的类型提供Into的反向实现——因为Number实现了From<i32>,所以i32自动拥有Into<Number>的实现。编译器可以直接推断.into()的目标类型是Number,因此编译通过。
- 对于
额外补充:强行让*i_ref.into()编译的方式
如果一定要保留*i_ref.into()的写法,你需要手动指定.into()的目标类型,同时补充对应的实现:
// 先给&i32实现Into<Number> impl From<&i32> for Number { fn from(n: &i32) -> Self { Self { n: *n } } } pub fn main() { let i = 5; let i_ref = &i; // 手动指定into的目标类型为&Number,解引用后得到Number let m: Number = *i_ref.into::<&Number>(); println!("{}", m.n); }
不过这种写法完全没必要,不如先解引用再调用.into()直观。
内容的提问来源于stack exchange,提问作者S.S.J
相关产品推荐
相关产品推荐

