I am doing a request, and via trait it will transform the result in any type I need, assuming the type implements FromBuffer.
In many cases this will magically do exactly what I want, but when I want to discard the result (no assignment to a variable) Rust still insists, that I manually specify the generic type: note: cannot satisfy _: FromBuffer
To me it seems there is no way to make this work without a turbofish or something like let _: () = .... Obviously Rust is not wrong here, but I wonder why can't the return type in the case of no assignment be infered to be ()? Most likely there is a good reason for that?
because it's a generic type, there's potentially multiple candidate types can be used, and it will affect the generated code, which will have observable behavior to the program state. in your example, different types can have different implementation for the FromBuffer trait, the compiler doesn't know which one to pick.
in your particular case, it might be possible to arbitrarily pick one type (e.g. the unit type ()) and the resulted code can be the same, but this is a special case which cannot be made into a reasonable general rule.
in general, it's not possible to arbitrarily pick a type in a unconstraint generic context, because what type to pick can change the behavior of the progarm. here's a contrived example:
// the bound for the return type, similar to `Default`
trait ReturnType {
from_thin_air() -> Self;
}
struct Foo {}
struct Bar {}
impl ReturnType for Foo { println!("do this"); Foo {} }
impl ReturnType for Bar { println!("do that"); Bar{} }
fn value_from_thin_air<Ret: ReturnType>() -> Ret { Ret::from_thin_air() }
fn main() {
// what return type should the compiler pick ???
value_from_thin_air();
}
// what's more, even if the `ReturnType` trait is all implemented exactly the same way
// the program behavior can still be changed depending on what concrete type to pick
// for example, they might have desctructors
impl Drop for Foo {
fn drop(&mut self) { println!("drop this"); }
}
impl Drop for Bar {
fn drop(&mut self) { println!("drop that"); }
}
As a slightly less contrived example, it would seem quite reasonable on the surface for any type implementing FromBuffer to assert! that the given buffer contains an appropriate number and format of bytes to construct the type. Without a type annotation of some kind, the compiler doesn't whether from_buffer() should return normally or panic on any given buffer.