Using .into () when type inference is not possible

I hope I can use .into() to convert the value to a context where type inference is not possible. This is usually when I want to convert a temporary value to some other type to pass it into a universal function. See the following code for an example ( 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 } 

I get an error:

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

How to tell the compiler that I want to convert to a i32 ?

I can make it work correctly, explicitly Into::<i32>::into(a) Into with arguments like: Into::<i32>::into(a) . This is more verbose and explicit than I had hoped to achieve, especially in a context where I did not import Into ( std::convert::Into::<i32>::into(a) ). a.into::<i32>() would be acceptable, but this is not the place where type arguments go.

a.into() as i32 will look good, but this exact syntax does not work.

Is there a trick I'm missing out on?

+8
source share
4 answers

You can use 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)); } 

You can read more about this in the documentation for the convert module .

+8
source

Apparently this is possible on Rust nightly with a type label that seems to be a function designed for this use case ( 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); } 

Since this is available in an experimental function, it may be reasonable to conclude that otherwise it is not available in the native language.

+7
source

I do not think there is a better way. Since the type parameter is in the attribute, and not in the into() method, the TurboFish into::<i32>() operator does not work. As you said, you can make it work using the full syntax:

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

Note that Into re-exported to std::prelude , which means you never need to specify the full path, since the trait is always in scope.

Of course, there is always the opportunity to bind your temporary file to a name and use annotation like let -binding:

 let tmp: i32 = a.into(); 

Perhaps in the future it will be better! There is an RFC such as Ascription for Expressions , which has already been adopted and implemented. The function is still unstable, but if it is implemented, you can write something like:

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

You can simply annotate the type of result by assigning it to a variable.

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

Source: https://habr.com/ru/post/1261451/


All Articles