@@ -411,8 +411,9 @@ fn factory() -> &(Fn(i32) -> i32) {
411
411
```
412
412
413
413
Right. Because we have a reference, we need to give it a lifetime. But
414
- our ` factory() ` function takes no arguments, so elision doesn’t kick in
415
- here. What lifetime can we choose? ` 'static ` :
414
+ our ` factory() ` function takes no arguments, so
415
+ [ elision] ( lifetimes.html#lifetime-elision ) doesn’t kick in here. Then what
416
+ choices do we have? Try ` 'static ` :
416
417
417
418
``` rust,ignore
418
419
fn factory() -> &'static (Fn(i32) -> i32) {
@@ -432,7 +433,7 @@ But we get another error:
432
433
``` text
433
434
error: mismatched types:
434
435
expected `&'static core::ops::Fn(i32) -> i32`,
435
- found `[closure <anon>:7:9: 7:20]`
436
+ found `[closure@ <anon>:7:9: 7:20]`
436
437
(expected &-ptr,
437
438
found closure) [E0308]
438
439
|x| x + num
@@ -441,21 +442,17 @@ error: mismatched types:
441
442
```
442
443
443
444
This error is letting us know that we don’t have a ` &'static Fn(i32) -> i32 ` ,
444
- we have a ` [closure <anon>:7:9: 7:20] ` . Wait, what?
445
+ we have a ` [closure@ <anon>:7:9: 7:20] ` . Wait, what?
445
446
446
447
Because each closure generates its own environment ` struct ` and implementation
447
448
of ` Fn ` and friends, these types are anonymous. They exist just solely for
448
- this closure. So Rust shows them as ` closure <anon> ` , rather than some
449
+ this closure. So Rust shows them as ` closure@ <anon> ` , rather than some
449
450
autogenerated name.
450
451
451
- But why doesn’t our closure implement ` &'static Fn ` ? Well, as we discussed before,
452
- closures borrow their environment. And in this case, our environment is based
453
- on a stack-allocated ` 5 ` , the ` num ` variable binding. So the borrow has a lifetime
454
- of the stack frame. So if we returned this closure, the function call would be
455
- over, the stack frame would go away, and our closure is capturing an environment
456
- of garbage memory!
457
-
458
- So what to do? This _ almost_ works:
452
+ The error also points out that the return type is expected to be a reference,
453
+ but what we are trying to return is not. Further, we cannot directly assign a
454
+ ` 'static ` lifetime to an object. So we'll take a different approach and return
455
+ a "trait object" by ` Box ` ing up the ` Fn ` . This _ almost_ works:
459
456
460
457
``` rust,ignore
461
458
fn factory() -> Box<Fn(i32) -> i32> {
@@ -471,7 +468,7 @@ assert_eq!(6, answer);
471
468
# }
472
469
```
473
470
474
- We use a trait object, by ` Box ` ing up the ` Fn ` . There’s just one last problem:
471
+ There’s just one last problem:
475
472
476
473
``` text
477
474
error: closure may outlive the current function, but it borrows `num`,
@@ -480,8 +477,12 @@ Box::new(|x| x + num)
480
477
^~~~~~~~~~~
481
478
```
482
479
483
- We still have a reference to the parent stack frame. With one last fix, we can
484
- make this work:
480
+ Well, as we discussed before, closures borrow their environment. And in this
481
+ case, our environment is based on a stack-allocated ` 5 ` , the ` num ` variable
482
+ binding. So the borrow has a lifetime of the stack frame. So if we returned
483
+ this closure, the function call would be over, the stack frame would go away,
484
+ and our closure is capturing an environment of garbage memory! With one last
485
+ fix, we can make this work:
485
486
486
487
``` rust
487
488
fn factory () -> Box <Fn (i32 ) -> i32 > {
0 commit comments