R and U appear in associated type bounds (e.g. Output = U, function return types desugar to something very similar). Associated types are completely determined by the other types appearing in the bounds, and hence are considered used (assuming the others are used).
A more conventional definition of this struct would be
struct AsyncWrapper<F>(F);
The definition of the struct doesn't depend on any of the constraints you'e applying to F, so they should generally not appear there. You'd have to repeat them anyways in the impl blocks, and that's the more appropriate place for them.
The constraints on F, and the additional parameters needed to support them, would normally only be applied to the specific functions that need them, or to the impl blocks containing those functions. You'd have the same problem of unconstrained type parameters in those cases, perhaps, so the other answers are still useful, but I thought I'd point this out. One solution might be shaped like this:
doesn't count as constraint for T according to the rules you mentioned. Maybe I'm completely wrong, but from what I've learned there's also always a compiler generated impl of the Fn trait for the Fn item where as far as I can tell T should be mentioned in the impl trait reference (first rule should apply?).
You can have such functions on stable too, it's just that you're currently limited to parameters that differ only by lifetimes: for<'a> fn(&'a i32) implements Fn(&'static i32), Fn(&'some_random_lifetime i32), etc etc
I don't know maybe I've just a mental block right now but if you argue like that, you can also say that for eg the AT Rstands for you can choose an arbitrary concrete type:
R is an associated type, which means that if all the "input" types of the trait bound (F and T in the original post) are constrained then R will be constrained too, because you can't write two implementations for the same trait. i..e the following errors:
The difference is in the fact that even if you may supply different T you get back one, and fixedR for each T.
If you pick T you no longer may change R. But T is not similarly constrained.
One may imagine a different language where T and R would be treated symmetrically and where even associated items would be trated similarly to generic params, it's all plausible (read about how Prolog does that, that's not a new thing)… but Rust doesn't work like that.