当不可能推理类型时,请使用诸如.into()之类的通用特征方法



我希望能够使用 .into()在不可能推理的上下文中转换一个值。这通常是当我想将临时值转换为其他类型以将其传递到通用函数时。请参阅以下代码以获取示例(游乐场):

use std::convert::*;
struct NewType(pub i32);
impl From<NewType> for i32 {
    fn from(src: NewType) -> i32 {
        src.0
    }
}
fn main() {
    let a = NewType(5);
    println!("{}", a.into()); // Understandably won't compile
}

我得到错误:

error[E0282]: type annotations needed
  --> src/main.rs:13:20
   |
13 |     println!("{}", a.into());
   |                    ^^^^^^^^ cannot infer type for `T`

如何正确告诉编译器我要将a转换为i32

我可以通过使用类型参数(Into::<i32>::into(a))明确喂食Into来使其正常工作。这比我希望能够实现的更详细和明确,尤其是在我没有导入Intostd::convert::Into::<i32>::into(a))的情况下。a.into::<i32>()是可以接受的,但这不是类型参数所在的地方。

a.into() as i32看起来不错,但是这种确切的语法不起作用。

我缺少一个技巧吗?

您可以使用From::from

use std::convert::*;
struct NewType(pub i32);
impl From<NewType> for i32 {
    fn from(src: NewType) -> i32 {
        src.0
    }
}
fn main() {
    let a = NewType(5);
    println!("{}", i32::from(a));
}

您可以在convert模块的文档中阅读有关它的更多信息。

我认为没有更好的方法。由于类型参数在性状上,而不是方法into(),因此涡轮FAMECON into::<i32>()不起作用。正如您所说,您可以使用完整的syntax来使其正常工作:

Into::<i32>::into(a)

请注意,Intostd::prelude中重新效仿,这意味着您永远不必指定完整的路径,因为特征始终处于范围内。

当然,也总是有可能将您的临时性绑定到名称并使用let-结合的类型注释:

let tmp: i32 = a.into();

不过,将来可能会更好!有一个已经接受和实施的表达式 rfc的类型。该功能仍然不稳定,但是如果实现了,则可以写出类似的内容:

println!("{}", (a.into(): i32));   // still unstable :/

显然,这在rust nightly with type castription中可能是可能的,这似乎是为此用例设计的功能(游乐场):

#![feature(type_ascription)]
use std::convert::*;
struct NewType(pub i32);
impl From<NewType> for i32 {
    fn from(src: NewType) -> i32 {
        src.0
    }
}
fn main() {
    let a = NewType(5);
    println!("{}", a.into(): i32);
}

由于这在实验功能中可用,因此可以合理地得出结论,否则该语言中缺少了适当的语言。

您可以通过将结果分配给变量来简单地注释结果的类型。

let b: i32 = a.into();
println!("{}", b);

您可以将函数定义隐藏在某个地方以获取其余代码看起来不错。

use std::convert::*;
struct NewType(pub i32);
impl From<NewType> for i32 {
    fn from(src: NewType) -> i32 {
        src.0
    }
}
fn main() {
    let a = NewType(5);
    println!("{}", a.get_i32());
}
mod r#impl {
    impl super::NewType {
        pub fn get_i32(self) -> i32 {
            self.into()
        }
    }
}

最新更新