HRTB bug when for<'a> Fn(<X as Trait<'a>>::Assoc)?

Am I facing a HRTB bug?

trait Variable<'a> {
    type Type;
}

impl Variable<'_> for () {
    type Type = ();
}

fn check<F, T>(f: F)
where
    F: Fn(T),
    F: for<'a> Fn(<T as Variable<'a>>::Type),
    T: for<'a> Variable<'a>,
{
}

fn main() {
    fn fn_test(_: ()) {}
    check(fn_test);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0631]: type mismatch in function arguments
  --> src/lib.rs:19:11
   |
18 |     fn fn_test(_: ()) {}
   |     ----------------- found signature of `fn(()) -> _`
19 |     check(fn_test);
   |     ----- ^^^^^^^ expected signature of `for<'a> fn(<() as Variable<'a>>::Type) -> _`
   |     |
   |     required by a bound introduced by this call
   |
note: required by a bound in `check`
  --> src/lib.rs:12:8
   |
9  | fn check<F, T>(f: F)
   |    ----- required by a bound in this
...
12 |     F: for<'a> Fn(<T as Variable<'a>>::Type),
   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`

For more information about this error, try `rustc --explain E0631`.
error: could not compile `playground` due to previous error

HRTB projections strike again?.

Yes, should be a bug; seems to have to do with type inference, too, since the code compiles if you call it as check::<_, ()>(fn_test).

You can also make it compile by changing it to check(|x| fn_test(x)).

Seems to only be buggy with fn items, too. Closures work as in

let fn_test = |x: ()| ();
check(fn_test);

Edit: Actually, another failure case is

fn blah(fn_test: impl Fn(())) {
    check(fn_test);
}

The same workarounds work here, too.

Edit2: I feel like this is a different bug than the one @H2CO3 linked.

4 Likes

Thanks for investigating. I'm filing it as a bug!

Edit: reported in #90875

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.