rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.24k stars 12.57k forks source link

Type inference problem #95358

Open jongiddy opened 2 years ago

jongiddy commented 2 years ago

I originally posted this at https://users.rust-lang.org/t/type-inference-failure-in-simple-generic-method-call/73423 but didn't get much response, apart from agreement that this is weird.

This code wraps the reqwest::ReqwestBuilder::header<K, V> method with a function that has the same signature. Both functions have generic parameters K and V that should be easily and independently inferred from the types passed to each function.

fn set_sensitive_header<K, V>(
    builder: reqwest::RequestBuilder,
    key: K,
    value: V,
) -> reqwest::RequestBuilder
where
    http::header::HeaderName: TryFrom<K>,
    <http::header::HeaderName as TryFrom<K>>::Error: Into<http::Error>,
    http::HeaderValue: TryFrom<V>,
    <http::HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
    V: Copy
{
    match http::HeaderValue::try_from(value) {
        Ok(mut header_value) => {
            header_value.set_sensitive(true);
            builder.header(key, header_value)
            // builder.header::<K, http::HeaderValue>(key, header_value)
        }
        Err(_) => builder.header(key, value),
    }
}

This fails with:

error[E0308]: mismatched types
  --> src/lib.rs:16:33
   |
1  | fn set_sensitive_header<K, V>(
   |                            - this type parameter
...
16 |             builder.header(key, header_value)
   |                                 ^^^^^^^^^^^^ expected type parameter `V`, found struct `HeaderValue`
   |
   = note: expected type parameter `V`
                      found struct `HeaderValue`

Adding the turbofish, as in the commented-out line, fixes the problem.

The generic types K and V on the header method should be trivially inferred from the supplied parameters. So this seems like a failure in type inference.

I thought this might be related to the where clauses constraining the concrete HeaderValue type, but changes like using TryFrom<V> + From<HeaderValue> did not fix it.

jongiddy commented 2 years ago

@rustbot label A-inference