Rustコトハジメ

プログラミング言語Rustと競プロに関する情報をお届けします。

The fact that closure's super traits are generated by compiler

In the previous post, we have learned that closure is generated by the compiler (e.g. The compiler generates a class implements FnMut for a closure that mutates the captured environment) but how super traits for the closure is generated was not revealed.

www.rustforbeginners.com

What is super traits? The three types of closures have relations Fn: FnMut and FnMut: FnOnce so for example a closure that doesn't mutate the environment and implements Fn should also implement FnMut and FnOnce.

In the following post, we visited the Iterator's functional programming aspect and every functions, to our surprise, take FuMut instead of Fn. That's super traits implementations that enables us to give Fn to FnMut argument.

www.rustforbeginners.com

In this post, we will visit a document about how super traits are implemented automatically.

I couldn't find anything in the stdlib

In Rust, cases like this is realized by so-called blanket implementations and my first step was finding the blanket implementations that type

impl<A, F> FnMut<A> for F where F : Fn<A>
impl<A, F> FnOnce<A> for F where F: FnMut<A>

but unfortunately I couldn't find anything at all.

There are blanket implementations for closures in

function.rs.html -- source

but I didn't think they are what I was looking for. The blanket implementations in the source code is the followings

  • impl Fn for &F where F: Fn
  • impl FnMut for &F where F: Fn
  • impl FnOnce for &F where F: Fn
  • impl FnMut for &mut F where F: FnMut
  • impl FnOnce for &mut F where F: FnMut

and they are all for F references.

If these references are magically translated into owned F and become what we want there wouldn't be the macros like I've shared you in the following post.

www.rustforbeginners.com

Finally, I find the article

Finally, I find the article.

Finding Closure in Rust | Huon on the internet

This article is trustable because it is referred by the official blog (Abstraction without overhead: traits in Rust | Rust Blog). In this article says

  • and similarly every closure implementing FnMut can also implement FnOnce
  • the former is more flexible, so the compiler implements FnMut for closure (and also FnOnce)

means the super traits are also implemented by the compiler.

That compiler generates the super trait implementations at the same time sounds reasonable to me because they are anyway required for compile and there is no reason to generate them by static dispatch.