You seem to have hit a quirk in the compiler. The toilet closure (|_|()
) generalizes into a function which is generic over its input type (<T> Fn(T)
),
but in such a way that does not fulfill the intended constraint over the lifetime of T
. What we need here is a function that is generic over the lifetime of the input due to the bound for<'a> Fn(&'a str)
in the implementation of Subscriber
for Task<T>
.
(Due to the current lifetime elision rules, the higher-ranked trait bound in Subscriber
can be written without explicitly indicating for<'a>
. This expansion was made in the previous paragraph for clarity.)
This is made a bit clearer by the compiler if you try to actually use the Task
value as a Subscriber
:
let mut task = Task(Some(|_| ()));
task.recv("Message");
The error message:
error[E0599]: no method named `recv` found for struct `Task<[closure@src/main.rs:19:30: 19:36]>` in the current scope
--> src/main.rs:20:10
|
5 | / pub struct Task<T>(pub Option<T>)
6 | | where
7 | | T: Fn(&str);
| | -
| | |
| |________________method `recv` not found for this
| doesn't satisfy `_: Subscriber`
...
19 | let mut task = Task(Some(|_| ()));
| ------
| |
| doesn't satisfy `<_ as std::ops::FnOnce<(&str,)>>::Output = ()`
| doesn't satisfy `_: std::ops::Fn<(&str,)>`
20 | task.recv("Message");
| ^^^^ method not found in `Task<[closure@src/main.rs:19:30: 19:36]>`
|
= note: the method `recv` exists but the following trait bounds were not satisfied:
`<[closure@src/main.rs:19:30: 19:36] as std::ops::FnOnce<(&str,)>>::Output = ()`
which is required by `Task<[closure@src/main.rs:19:30: 19:36]>: Subscriber`
`[closure@src/main.rs:19:30: 19:36]: std::ops::Fn<(&str,)>`
which is required by `Task<[closure@src/main.rs:19:30: 19:36]>: Subscriber`
By explicitly marking the closure's single input parameter as a reference, the closure will then no longer generalize over the parameter type T
, but over a higher-ranked lifetime of the reference input 'a
in &'a _
.
let mut task = Task(Some(|_: &_| ()));
task.recv("Message");
Playground.
While not impossible, adjusting the compiler to successfully infer the right type for the original closure would possibly require substantial changes to the current monomorphization rules.
See also:
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…