How I can get a concrete type from an opaque type.
use std::fmt::Display;
fn fx<T: Display>(x: T)-> impl Display {
x
}
fn main() {
let y: i32 = fx(10);
let xy = y + 10;
println!("Hello World {}", xy);
}
Got error message
error[E0308]: mismatched types
--> main.rs:16:18
|
10 | fn fx<T: Display>(x: T)-> impl Display {
| ------------ the found opaque type
...
16 | let y: i32 = fx(10);
| --- ^^^^^^ expected `i32`, found opaque type
| |
| expected due to this
|
= note: expected type `i32`
found opaque type `impl std::fmt::Display`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.
I can’t add returned value of integer type with anoter integer value cuz real type of returned vale is hidden.
7
You can recover a specific type from an unknown generic by comparing their TypeId
s (similar to how Any::downcast
works). This requires the types to be 'static
and of course it is fallible since fx
can change its implementation behind the impl Display
at any time:
use std::fmt::Display;
use std::any::TypeId;
fn fx<T: Display + 'static>(x: T)-> impl Display + 'static {
x
}
fn downcast_owned<T: 'static, U: 'static>(t: T) -> Result<U, T> {
if TypeId::of::<T>() == TypeId::of::<U>() {
// SAFETY: this is safe because we've verified that `T` and `U` are the same
// and thus we can `read`+`forget` to "move" the value from `t` to `u`.
let u = unsafe { std::ptr::read(&t as *const _ as *const U) };
std::mem::forget(t);
Ok(u)
} else {
Err(t)
}
}
fn main() {
let y = fx(10);
if let Ok(y) = downcast_owned::<_, i32>(y) {
let xy = y + 10;
println!("Hello World {}", xy);
}
}
Hello World 20
Playground link
As mentioned in the comments, this is generally not a good idea and it would be better to change the return type to more appropriately describe what you want it to do.
You can just spell out the type in its full form. If that doesn’t work, you should rethink the logic a bit. Think like the (rust) compiler. If you return an opaque type (basically a trait object), it can only be sure that the functions implemented in the given trait will work on it. You can give it a bit more context, as shown below.
use std::fmt::Display;
fn fx<T: Display>(x: T) -> T /* now returns T instead */ {
x
}
fn main() {
let y: i32 = fx(10);
let xy = y + 10;
println!("Hello World {}", xy);
}
1