Default type ignored by type inference

backblaze-b2 has a function list_buckets() that returns Result<Vec<Bucket<InfoType>>,B2Error>.

However, if I write

let buckets = auth.list_buckets(&client).unwrap();

I get

43 |     let buckets = auth.list_buckets(&client).unwrap();
   |         -------        ^^^^^^^^^^^^ cannot infer type for type parameter `InfoType` declared on the associated function `list_buckets`
   |         |
   |         consider giving `buckets` the explicit type `std::vec::Vec<backblaze_b2::raw::buckets::Bucket<InfoType>>`, where the type parameter `InfoType` is specified

Instead I have to write

let buckets: Vec<Bucket> = auth.list_buckets(&client).unwrap();

The definition of Bucket is:

pub struct Bucket<InfoType=JsonValue> {
    ...
    pub bucket_info: InfoType,
    ...
}

The compiler already knows from the return type that buckets is a Vec<Bucket>. When I write let buckets: Vec<Bucket> I'm just stating the obvious, aren't I?

Why does it use the default type only when I write the redundant <Bucket>?

Your code is responsible to pick/specify or infer the type for list_buckets type parameter. Rust does not support a default https://github.com/rust-lang/rust/issues/36887

Alternatively you could have written;
let buckets = auth.list_buckets::<JsonValue>(&client).unwrap();

By supplying the type to the variable you allow the above to be inferred.

That's exactly my point, I could have written that but I didn't have to, because that type parameter has a default. It's just that the default gets ignored when inferring the type of buckets, unless I re-specify the return type, then the default is applied. (Note that let buckets: Vec<Bucket> is enough, I didn't have to write let r: Vec<Bucket<JsonValue>> so the default is not discarded completely.)

If you were to write; let buckets: Vec<Bucket<_>> I expect you would get the error. By not specifying <_> the code takes the default for the type and then can infer.

Indeed let buckets: Vec<Bucket<_>> = ... leads to cannot infer type and let buckets: Vec<Bucket> = ... takes the default type. That still doesn't explain why let buckets = ... doesn't take the default type, even though the compiler already knows for sure that buckets is Vec<Bucket>.

It doesn't.

Vec<Bucket> is equivalent to Vec<Bucket<JsonValue>>, due to the default type parameter. But code on the right side can potentially produce any Vec<Bucket<_>> - compiler doesn't have the information necessary to fill the _.

It could use the default type? Isn't that what a default is for, to replace things that were left unspecified?

A default type is only applied when you actually write the name of the type, i.e. it turns Bucket into Bucket<JsonValue>. It has no effect on type inference.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.