Why variable y is infering a trait rather than a type for closure?

fn main(){
    let x = "sam".to_string();
    let y: impl FnOnce() -> String = ||  x;  
}

Here i'm using a closure , where the compile is infering a impl trait rather than a type. According to rust book, a closure is a anonymous function. And we can only apply trait to type. On what basis compiler is infering like this?

The types of closures (and function items too) are anonymous types you can't name. As such you can only refer to them by their properties, namely implementing a trait, and usually the ones you care for closures are the Fn* traits.

I'm not sure what your question is, and what it has to do with the code, because neither makes sense:

  • the code doesn't compile;
  • but if it did, the compiler wouldn't have room to infer anything, since every type is explicitly specified;
  • and you are implying that impl Trait is a trait, which it isn't – impl Trait is a type.

So, what's your actual question?

I want to to know the return types of closure in general. According to my knowledge closure is anonymous function. Im not concerned about * the code doesn't compile;. I just want to know how compiler is infering a trait for closure

It doesn't "infer a trait", but it does choose some subset of traits to implement for the anonymous closure type.

See the below link (and the rest of that page).

https://doc.rust-lang.org/reference/types/closure.html#call-traits-and-coercions

2 Likes

The type of a closure is an anonymous, struct-like type, of which the "fields" contain captured environment, and callability is provided by the compiler implementing the applicable Fn* traits (FnOnce, FnMut, and/or Fn).

I still don't get that part. There was no "inference" in anything we talked about this thread so far.

Please paste below code in any ide with rust-analyzer, you can see the compiler inference for variable y

fn main(){
    let x = "sam".to_string();
    let y = ||  x;  
}

The IDE is not the compiler. That hint is only your IDE trying to be "helpful" and show you something in place of the unnameable type, and you are misinterpreting its hint (or taking it too literally). (Which is one of many reasons for not using any sort of IDE especially while you are a beginner.)

The compiler doesn't infer the type of y to literally be impl FnOnce() -> String or whatever. The compiler creates its own internal type and that's what the type of the closure is.

impl Trait is merely a construct for naming capabilities of a type without having to name the type itself, which is helpful if the type cannot be named (like closures) or would be too verbose (as in the case of deeply-nested iterator adapters) or you intentionally want to hide the concrete type for API stability. It's a placeholder for a concrete type. Returning an impl Trait from a function does not change the concrete type of the returned value – it's just that the caller won't know what it is, only what trait(s) it implements.

6 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.