在无法进行类型推断时使用.into()

Mag*_*off 14 type-conversion rust

我希望能够.into()在不可能进行类型推断的上下文中转换值.这通常是在我想将临时值转换为其他类型以将其传递给泛型函数时.有关示例(playground),请参阅以下代码:

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
}
Run Code Online (Sandbox Code Playgroud)

我收到错误:

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

如何正确告诉编译器我想要转换ai32

我可以通过显式Into提供类型参数来使其正常工作:Into::<i32>::into(a).这比我希望能够实现的更详细和明确,特别是在我没有import Into(std::convert::Into::<i32>::into(a))的上下文中.a.into::<i32>()是可以接受的,但这不是类型参数的去处.

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

有没有我缺少的技巧?

Sim*_*mer 11

你可以使用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));
}
Run Code Online (Sandbox Code Playgroud)

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

  • 为什么人们可以期望有一个 `From`: *"库作者不应该直接实现 [Into] trait,而应该更喜欢实现 From trait,这提供了更大的灵活性并免费提供了等效的 Into 实现,这要归功于标准库中的全面实现。”* - 来自 `Into` 的文档。 (4认同)

Luk*_*odt 9

我不认为有更好的方法.由于类型参数在特征上,而不是方法into(),因此涡轮机操作员into::<i32>()不起作用.正如您所说,您可以使用完全限定语法使其工作:

Into::<i32>::into(a)
Run Code Online (Sandbox Code Playgroud)

注意,这Into是重新导出的std::prelude,这意味着您永远不必指定完整路径,因为特征始终在范围内.

当然,也总是可以将临时绑定到名称并使用let-binding 的类型注释:

let tmp: i32 = a.into();
Run Code Online (Sandbox Code Playgroud)

不过,未来可能会更好!表达式 RFC类型归属已经被接受和实现.该功能仍然不稳定,但如果实现它你可以写如下:

println!("{}", (a.into(): i32));   // still unstable :/
Run Code Online (Sandbox Code Playgroud)


Mag*_*off 7

显然,这可以在Rust nightly上使用类型归属,这似乎是为这个用例(playground)设计的一个特性:

#![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);
}
Run Code Online (Sandbox Code Playgroud)

由于这是在实验性功能中可用的,因此可能有理由得出结论认为它在语言中缺失.