7

I'm aware that Rust allocates on the stack by default, but the paper Ownership is Theft says that Rust closures are typically allocated dynamically (which I took to mean "on the heap").

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
TJB
  • 75
  • 4
  • 6
    That paper was published in October 2015. Unboxed closures were first implemented in January of that year. I can't read the paper, but it's very likely that substantial parts of it were written based on a pre-1.0 version of Rust in which closures *were* boxed by default (equivalent to today's `Box`) When you're reading research it's often essential to keep the date in mind. – trent Feb 15 '21 at 15:28
  • I discovered this information while researching - but wanted to double-check since I couldn't find any Rust documentation saying that closures were definitely stack-allocated by default. (Which of course doesn't mean it doesn't exist.) Thank you anyway though! – TJB Feb 15 '21 at 15:31
  • 4
    If you're interested in the history, the [release notes for 1.0.0-alpha](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-100-alpha-2015-01-09) say: "Closures have been [completely redesigned](https://smallcultfollowing.com/babysteps/blog/2014/11/26/purging-proc/) to be implemented in terms of traits, can now be used as generic type bounds and thus monomorphized and inlined, or via an opaque pointer (boxed) as in the old system. The new system is often referred to as 'unboxed' closures." – trent Feb 15 '21 at 15:33
  • That's exactly the kind of thing I was looking for! Thank you so much – TJB Feb 15 '21 at 15:35

1 Answers1

11

They are located on the stack by default. This can be proven by showing that closures are allowed in environments where there is no allocator, such as in libcore. From core::Option::map:

pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U>

As trentcl notes:

If you're interested in the history, the release notes for 1.0.0-alpha say:

Closures have been completely redesigned to be implemented in terms of traits, can now be used as generic type bounds and thus monomorphized and inlined, or via an opaque pointer (boxed) as in the old system. The new system is often referred to as 'unboxed' closures.

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 1
    Thank you for the quick answer! Do you have any links to Rust documentation which says as much? (I'm writing a paper for University coursework.) – TJB Feb 15 '21 at 15:26
  • Thank you for the additional example as proof! – TJB Feb 15 '21 at 15:37