Puzzled by anonymous closures that do not compile

In the code below, the lines using the string "not ok" do not compile, they get a Rust compiler error "Mismatched types".

I do not understand why the compiler rejects these constructs, as both variables f3 and f4 define closures that return a struct X when called.

Coming from a Scala background, I would appreciate input from Rust experts on why these calls to f3 and f4 fail.

Many thanks !

JL

=================

struct X {
  some_string: String
}

impl X {

  pub fn consume_closure<T>(s: String, f: fn(&String) -> T) -> T {
    f(&s)
  }

  fn f1(s: &String) -> X { X { some_string: s.clone() } }

  fn test() {

    let f2 = |s: &String|-> X { X { some_string: s.clone() } };

    let f3: fn() -> X = || { Self::f1(&"Hello".to_string()) };

    let f4: fn(&String) -> X = |s: &String| { Self::f1(s) };

    let x: X = Self::consume_closure("ok".to_string(), Self::f1);
    let x: X = Self::consume_closure("ok".to_string(), f2);
    let x: X = Self::consume_closure("ok".to_string(), |s: &String| { X { some_string: s.clone() } });
    let x: X = Self::consume_closure("not ok".to_string(), |s: &String| { f3() });
    let x: X = Self::consume_closure("not ok".to_string(), |s: &String| { f4(s) });
    let x: X = Self::consume_closure("ok".to_string(), |s: &String| { Self::f1(s) });
  }
}

fn(...) is a function pointer type which can't represent any closure that captures a variable. f3 and f4 are local variables of the test() function, which are captured in the anonymous closures on the "not ok" lines.

To accept arbitrary closures, define consume_closure like this instead:

  pub fn consume_closure<T, F>(s: String, f: F) -> T
    where F:FnOnce(&String)->T
  {
    f(&s)
  }
1 Like

Dear Mr. Euler, you perfectly identified the issue. I did learn something important today, many thanks! JL

1 Like