Closure argument coercion

In the following snippet, a function that is impl Fn(&str) can't be passed into a function that expects an impl Fn(&String), but the same item can be used if wrapped in a closure.

fn validate(input: &str) -> bool {
    !input.is_empty()
}

fn main() {
    let input = Some("foo".to_string());
    // let _validated = (&input).as_ref().map(validate); // doesn't work
    let _validated = (&input).as_ref().map(|v| validate(v));
}

Playground link

I know there's some kind of coercion the compiler is doing here, but I don't know its mechanism or its bounds, or even what it's called. Obviously I've run into either a limitation or an intentional boundary.

What's going on here?

this is deref coercion in action.

2 Likes

alternative 1: use Option::as_deref() instead of Option::as_ref():

let _validated = (&input).as_deref().map(validate);

alternative 2: make validate() generic so it can accept &String as well as &str:

fn validate(input: &impl Deref<Target = str>) -> bool {
    !input.is_empty()
}
// or
fn validate(input: &impl AsRef<str>) -> bool {
    !input.as_ref().is_empty()
}
1 Like