I'm writing a function that accepts different trait implementors. One of them is a closure. Some closures need an argument type annotation and some don't, depending on their bodies.

Example (playground):

fn main() {
    bar(|x| x);
    bar(|x: bool| !x); // Why is the annotation needed?

trait Foo<T> {
    type Output;

impl<F: Fn(T) -> O, T, O> Foo<T> for F {
    type Output = O;

fn bar(_: impl Foo<bool, Output = bool>) {}
  • Why do some closures infer the argument type and others need annotation?

  • Is it possible to redesign trait or function to never require annotation?

My (invalid) reasoning is that inference is the same for both closures:

  1. bar needs Foo<bool, Output = bool>
  2. Only Fn(bool) -> bool implements Foo<bool, Output = bool>
  3. The closure must be |bool| -> bool

The fact that negation (Not trait) detaches the input type from the output type should not matter, but it seems to somehow be a crucial element.

  • 1
    I don't think that's the reason. Replacing !x with x | true removes need for annotation and BitOr is not implemented for T either. Feb 28, 2019 at 16:05
  • 1
    @CodeSandwich I realized that your bar fn also uses Foo<bool, i was considering it as Foo<T, so BitOr should act like that already, but i added some other options which works, it gets interesting please check : Playground Feb 28, 2019 at 20:22
  • 2
    Interestingly |x| !&x works, but |x| !*&x doesn't. Mar 1, 2019 at 0:12
  • 4
    Given this discussion, it seems to me that you are hitting a limitation of the type inference algorithm used, rather than a fundamental language rule. Mar 1, 2019 at 8:22
  • 5
    I've created a Rust issue. Mar 1, 2019 at 10:22


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.