-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Open
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
Code
use std::io::Read;
pub trait HttpClient {
fn get(&self, url: &str) -> Result<Box<dyn Read>, std::io::Error>;
}
struct DummyHttpClient<T> {
responder: T,
}
impl<T> HttpClient for DummyHttpClient<T>
where
T: Fn(&str) -> Result<Box<dyn Read>, std::io::Error>,
{
fn get(&self, url: &str) -> Result<Box<dyn Read>, std::io::Error> {
(self.responder)(url)
}
}
struct UserBuilder {
client: Option<Box<dyn HttpClient>>,
}
impl UserBuilder {
pub fn new() -> Self {
Self { client: None }
}
/// Set the HTTP client to use for requests.
pub fn http_client(mut self, client: Box<dyn HttpClient>) -> Self {
self.client = Some(client);
self
}
}
fn test_custom_http_client() {
let http_client = Box::new(DummyHttpClient {
responder: |url| {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("DummyHttpClient cannot fetch {url}"),
))
},
});
let client = UserBuilder::new().http_client(http_client);
}
Current output
error: implementation of `FnOnce` is not general enough
--> src/lib.rs:45:49
|
45 | let client = UserBuilder::new().http_client(http_client);
| ^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&'2 str) -> Result<Box<dyn std::io::Read>, std::io::Error>` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2`
error: implementation of `Fn` is not general enough
--> src/lib.rs:45:49
|
45 | let client = UserBuilder::new().http_client(http_client);
| ^^^^^^^^^^^ implementation of `Fn` is not general enough
|
= note: closure with signature `fn(&'2 str) -> Result<Box<dyn std::io::Read>, std::io::Error>` must implement `Fn<(&'1 str,)>`, for any lifetime `'1`...
= note: ...but it actually implements `Fn<(&'2 str,)>`, for some specific lifetime `'2`
Desired output
It should suggest that adding explicit type annotation &str
to the argument of the closure would fix the issue. Or that you could add
where
T: Fn(&str) -> Result<Box<dyn Read>, std::io::Error>,
to the struct itself. That also fixes the issue.
Rationale and extra context
The current diagnostic is highly confusing and not helpful.
Other cases
Rust Version
❯ rustc --version --verbose
rustc 1.90.0 (1159e78c4 2025-09-14)
binary: rustc
commit-hash: 1159e78c4747b02ef996e55082b704c09b970588
commit-date: 2025-09-14
host: x86_64-unknown-linux-gnu
release: 1.90.0
LLVM version: 20.1.8
Anything else?
Originally reported here: https://users.rust-lang.org/t/strange-type-inference-around-fnonce-fn/134342
Metadata
Metadata
Assignees
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.