Parameter type `T` may not be long enough

I am trying to write a small program in Rust, but I cannot get it to work.

I reproduced the error in a smaller script:

fn main() {
    let name = String::from("World");
    let test = simple(name);
    println!("Hello {}!", test())
}

fn simple<T>(a: T) -> Box<Fn() -> T> {
    Box::new(move || -> T {
        a
    })
}

When I compile it, I get this error:

error[E0310]: the parameter type `T` may not live long enough
  --> test.rs:8:9
   |
7  |       fn simple<T>(a: T) -> Box<Fn() -> T> {
   |                 - help: consider adding an explicit lifetime bound `T: 'static`...
8  | /         Box::new(move || -> T {
9  | |             a
10 | |         })
   | |__________^
   |
note: ...so that the type `[closure@test.rs:8:18: 10:10 a:T]` will meet its required lifetime bounds
  --> test.rs:8:9
   |
8  | /         Box::new(move || -> T {
9  | |             a
10 | |         })
   | |__________^

I tried to add an explicit attachment to life T: 'static, as suggested by the error, but I get a new error:

error[E0507]: cannot move out of captured outer variable in an `Fn` closure
 --> test.rs:9:13
  |
7 |     fn simple<T: 'static>(a: T) -> Box<Fn() -> T> {
  |                           - captured outer variable
8 |         Box::new(move || -> T {
9 |             a
  |             ^ cannot move out of captured outer variable in an `Fn` closure
+2
source share
2 answers

Several things happen here, and all this is due to a little awkwardness around the semantics of movement and closure.

-, simple T. T , , , . Lifetime elision , . 'static, . , lifetime; . .

Fn, . , , , , (a) . , , , self &self. , :

trait FnOnce {
    type Output
    fn call(self) -> Output
}

trait Fn : FnOnce {
    fn call(&self) -> Output
}

// generated type
struct MyClosure<T> {
    a: T
}

impl<T> FnOnce for MyClosure<T> {
    fn call(self) -> T { self.a }
}

( , .)

, , , Fn, FnOnce. . FnMut, .

, . , , , self - (Box<T>, T ). , , . , . Box<FnOnce>. ( self), .

, ? Box<FnOnce> . .

Rust, FnBox: FnOnce, Box. , , : " , FnBox , Box<FnOnce()> ". , , , .

, , .

  • &'static T, . , , , .

  • , Rc<T>. - , , , . , .

  • . , , , . . , Rc<T> T, , .

+6

simple , T. , , , , 'static Type:

fn simple<T: 'static>(a: T) -> Box<Fn() -> T> {
    Box::new(move || -> T {
        a
    })
}

:

  |
7 | fn simple<T: 'static>(a: T) -> Box<Fn() -> T> {
  |                       - captured outer variable
8 |     Box::new(move || -> T {
9 |         a
  |         ^ cannot move out of captured outer variable in an `Fn` closure

name "" , "" - .

, , , - , - Fn.

, Fn, , : Fn() -> &'a T + 'a

fn main() {
    let name = String::from("World");
    let test = simple(&name);
    println!("Hello {}!", test())
}

fn simple<'a, T: 'a>(val: &'a T) -> Box<Fn() -> &'a T + 'a> {
    Box::new(move || -> &'a T {
        val
    })
}

impl (. PR # 35091, Rust 1.26 ):

fn main() {
    let name = String::from("World");
    let test = simple(&name);
    println!("Hello {}!", test())
}

fn simple<'a, T: 'a>(val: &'a T) -> impl Fn() -> &'a T {

    move || -> &'a T {
        val
    }
}
0

Source: https://habr.com/ru/post/1696323/


All Articles