I am hitting everybody's favorite error, where the expected type looks identical to the provided type even though the interpretation of the lifetime bounds differ in a subtle way that isn't part of the error message.
10/10 can confirm, that’s one of my “favorite” kind of errors, too. Maybe we should build a dedicated detection for this case, apologizing for the unhelpful error message, and recommending to report an issue.
I’ve written answers on similar problems in the past. E.g. here or here and the second one links some more places.
It’s possible to avoid the need for Box using trait, and @vague above provided an example, too, but those will unfortunately (for no good reason) not work with closures, only with (async) fn items. In that sense, the BoxFuture approach is more flexible/easy to use, at the minor downside of adding an allocation and some dynamic function calls.
(For example in both @vague's and @quinedot's playgrounds, you cannot write something like .dispatch_request(|x: &mut String| test_interpreter(x)) without incomprehensible and unavoidable compilation errors; so in particular, you can never pass a callback that needs to actually capture some data.)
@vague@quinedot@steffahn Wow! All three of your answers are wonderful and each provides a unique perspective. I am having a very hard time deciding which to mark as the solution.