Hi! I needed to provide users of my API with a mechanism to change reqwest's RequestBuilder headers, so I started making a struct to pass to a user provided closure:
use reqwest; // 0.12.9
use reqwest::RequestBuilder;
pub struct RequestHeaderBuilder(RequestBuilder);
impl RequestHeaderBuilder {
fn header_sensitive<K, V>(self, key: K, value: V, sensitive: bool) -> Self
where
reqwest::header::HeaderName: TryFrom<K>,
<reqwest::header::HeaderName as TryFrom<K>>::Error: Into<http::Error>,
reqwest::header::HeaderValue: TryFrom<V>,
<reqwest::header::HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
{
let mut value: reqwest::header::HeaderValue = value.try_into().map_err(|e| "A".to_string()).unwrap();
self.header(key, value)
}
fn header<K, V>(self, key: K, value: V) -> Self
where
reqwest::header::HeaderName: TryFrom<K>,
<reqwest::header::HeaderName as TryFrom<K>>::Error: Into<http::Error>,
reqwest::header::HeaderValue: TryFrom<V>,
<reqwest::header::HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
{
Self(self.0.header(key, value))
}
}
Lo and behold, this fails to compile with:
error[E0308]: mismatched types
--> src/lib.rs:15:20
|
7 | fn header_sensitive<K, V>(self, key: K, value: V, sensitive: bool) -> Self
| - expected this type parameter
...
15 | self.header(key, value)
| ------ ^^^^^ expected type parameter `V`, found `HeaderValue`
| |
| arguments to this method are incorrect
|
= note: expected type parameter `V`
found struct `HeaderValue`
note: method defined here
--> src/lib.rs:18:5
|
18 | fn header<K, V>(self, key: K, value: V) -> Self
| ^^^^^^ --------
Given the blanket impls
impl<T, U> TryFrom<U> for T where U: Into<T>
impl<T> From<T> for T
I would expect that
impl<T> TryFrom<T> for T
is also implemented, so I don't know why this won't work. In any case, I tried simplifying a bit and tried:
use reqwest; // 0.12.9
pub trait HeaderBuilder
where
Self: Sized,
{
fn header_sensitive<K, V>(self, key: K, value: V, sensitive: bool) -> Self
where
reqwest::header::HeaderName: TryFrom<K>,
<reqwest::header::HeaderName as TryFrom<K>>::Error: Into<http::Error>,
reqwest::header::HeaderValue: TryFrom<V>,
<reqwest::header::HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
{
let mut value: reqwest::header::HeaderValue = value.try_into().map_err(|e| "A".to_string()).unwrap();
let v2 = reqwest::header::HeaderValue::try_from(value);
todo!();
}
}
and got
error[E0308]: mismatched types
--> src/lib.rs:15:51
|
7 | fn header_sensitive<K, V>(self, key: K, value: V, sensitive: bool) -> Self
| - expected this type parameter
...
15 | let v2 = reqwest::header::HeaderValue::try_from(value);
| -------------------------------------- ^^^^^ expected type parameter `V`, found `HeaderValue`
| |
| arguments to this function are incorrect
|
= note: expected type parameter `V`
found struct `HeaderValue`
note: associated function defined here
--> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:687:8
|
687 | fn try_from(value: T) -> Result<Self, Self::Error>;
| ^^^^^^^^
Ok, so impl<T> TryFrom<T> for T
clearly is not working. And no, V
can't definitely be the expected argument to anything anymore. Then I tried changing to
let v2 = reqwest::header::HeaderValue::from(value);
And it compiles! So impl<T> From<T> for T
is working. In the midst of my attempt, I also tried
use reqwest; // 0.12.9
pub trait HeaderBuilder
where
Self: Sized,
{
fn header_sensitive<K, V>(self, key: K, value: V, sensitive: bool) -> Self
where
reqwest::header::HeaderName: TryFrom<K>,
<reqwest::header::HeaderName as TryFrom<K>>::Error: Into<http::Error>,
reqwest::header::HeaderValue: From<V>,
{
let mut value: reqwest::header::HeaderValue = value.into();
let v2 = reqwest::header::HeaderValue::from(value);
todo!();
}
}
And now if failes to compile with
error[E0308]: mismatched types
--> src/lib.rs:14:47
|
7 | fn header_sensitive<K, V>(self, key: K, value: V, sensitive: bool) -> Self
| - expected this type parameter
...
14 | let v2 = reqwest::header::HeaderValue::from(value);
| ---------------------------------- ^^^^^ expected type parameter `V`, found `HeaderValue`
| |
| arguments to this function are incorrect
|
= note: expected type parameter `V`
found struct `HeaderValue`
note: associated function defined here
--> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:585:8
|
585 | fn from(value: T) -> Self;
| ^^^^
No, I'm sorry, you can't do that! You can't have
let mut value: reqwest::header::HeaderValue = ...;
let v2 = reqwest::header::HeaderValue::from(value);
work in some cases and others not, regardless of what's in the ...
(except for errors caused by the ...
itself, obviously)! And what's with the insistence on the expected type V
!? It's a compiler bug, right? Right...?