Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the meaning of 'a: 'a in generic lifetime parameters?

Tags:

rust

lifetime

I have a strange piece of code:

#![allow(unused)]  fn f<'a>() {} fn g<'a: 'a>() {}  fn main() {     // let pf = f::<'static> as fn(); // (7)     let pg = g::<'static> as fn();    // (8)     //print!("{}", pf == pg); } 

The 7th line cannot be compiled if it is uncommented (with the error below), but the 8th line can be compiled.

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present  --> src/main.rs:7:18   | 7 |     let pf = f::<'static> as fn(); // (7)   |                  ^^^^^^^   | note: the late bound lifetime parameter is introduced here  --> src/main.rs:3:6   | 3 | fn f<'a>() {}   |      ^^ 

What is the meaning of 'a: 'a in line 4?

like image 742
iDuanYingJie Avatar asked Jan 02 '21 02:01

iDuanYingJie


People also ask

What is a lifetime parameter?

A generic lifetime parameter imposes a lifetime constraint on the reference(s) and the return value(s) of a function.

What is lifetime in Rust?

Lifetimes are what the Rust compiler uses to keep track of how long references are valid for. Checking references is one of the borrow checker's main responsibilities. Lifetimes help the borrow checker ensure that you never have invalid references.


1 Answers

I have found nothing in the rust documentation to confirm, but it seems that <'a: 'a> is short to qualify the output lifetime of the function (cf lifetime output in the documentation).

Here are some tests that seem confirm that :

#![allow(unused)]  fn f<'a>() {} fn g<'a: 'a>() {} fn h<'a: 'a>() -> &'a i32 { &5 } fn i<'a>() -> &'a i32 { &6 }  fn tst1<'b>() {    let w:&'b i32 = &6;    //let pj = f::<'b> as fn();    let pk = i::<'b> as fn() -> &'b i32; }  fn tst2<'b>() {    let pr = g::<'b> as fn(); } fn main() {     //let pf = f::<'static> as fn(); // (7)     let pg = g::<'static> as fn();    // (8)     let ph = h::<'static> as fn() -> &'static i32;     let pi = i::<'static> as fn() -> &'static i32;      //print!("{}", pf == pg); } 

This compile with Rustc 1.41.1. It's possible that recent updates impact this.

As you could see, let pi and let pk compile for fn i<'a>(), but not let pf nor let pj for fn f<'a>(). The fn i<'a>() only differs from fn f<'a>() as the former returns a value thus implying a output liftetime for the function.

The tst1 and tst2 verify this with inner lifetime of a function.

It cannot be 100% sure without documentation reference, but it seems that if you don't specify a output to your function, you still have, for function's pointers, to have a defined output lifetime, and <'a: 'a> seems implying that.

Regarding dtolnay quizz thanks to @Konstantin W, it seems that output lifetime of the function become earlier bounded with <'a: 'a> and the compiler doesn't scream in that case when assigning the 'static lifetime at the pointer assignation.

If that's the case, let pi and let pk compile for fn i<'a>() probably because the i function is fully defined in input like output then lifetime assignation could be done at pointer assignation (or the specified output implies earlier bounding for both input and output timeline, but I've a hard time believing that). Maybe an undocumented rust lifetime Elision rule too.

like image 197
Zilog80 Avatar answered Sep 27 '22 21:09

Zilog80