Why can a lifetime be not excluded in the definition of structure?

struct Point { x: u32, y: u32, } struct Line<'a> { start: &'a Point, end: &'a Point, } 

Here the only possible option for start and end fields is to have the same or longer lifetime than the Line variable that contains them. I can’t even imagine how you can use the lifetime specifier to say that fields have a shorter lifespan.

Why should I explicitly indicate the lifetime here? In this situation, election is not possible, and if so, why?

+9
source share
2 answers

When you define a structure, you do not establish a connection between the lifetime of the structure and the lifetime of the fields. As you pointed out, links in fields should live longer than structure.

Instead, you provide a “total lifetime” that will be specialized in creating the structure. This is similar to having a structure with a type parameter:

 struct Foo<T> foo: T, } 

When you create the structure, the compiler inserts the appropriate lifetimes (or types), and then checks that everything is still working.

Another thing is that you can specify the lifetime relative to each other:

 struct Line<'a, 'b: 'a> { start: &'a Point, end: &'b Point, } 

This suggests that start and end can have different lifetimes if end lifetimes exceed start times.

why doesn't the compiler make a lifetime exception for structures? Rust seems to do

(my emphasis)

I actually believe that Rust tends to be explicit, especially when it comes to defining top-level elements (such as functions, structures).

The rules for choosing a life cycle for functions have a rather small scope and were found empirically in RFC 141 with a high probability of success (87%). It was a very good ergonomic return on investment.

Perhaps at some point a similar deviation will occur for the structures, but this was not a big enough problem. If you are strongly interested in this, then I highly recommend that you seek consensus on the user forum , go to the developer forum, and ultimately make an RFC.

RFC 2093 adds a small number of findings. Before implementing it, you must specify that the generic type must survive the link as a link:

 struct Foo<'a, T: 'a> { start: &'a T, } 

There is no case where you don’t want this boundary, so after implementing the RFC, you can simply say:

 struct Foo<'a, T> { start: &'a T, } 
+7
source

Suppose we have a constructor for Line :

 impl<'a> Line<'a> { fn new(start: &'a Point, end: &'a Point) -> Line<'a> { // ' Line { start: start, end: end, } } } 

new returns a Line<'a> . To be able to parameterize the type with the lifetime (as we do here with Line<'a> ), this type must determine the parameters of the lifetime! Although the compiler can automatically determine the parameters of the lifetime, when necessary, it is much easier to understand that the type has parameters of the lifetime (or not), just looking at its definition in the source code.

The lifetime parameters in structures and transfers play an important role in the verification of borrowings. They let the compiler know that the structure retains values ​​for some values. Then the compiler may return errors when trying to change a value that has active values.

 fn main() { let mut start = Point { x: 2, y: 4 }; let end = Point { x: 7, y: 10 }; let line = Line::new(&start, &end); start.x = 3; // error: cannot assign to `start.x` because it is borrowed } 
0
source

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


All Articles