Perfect Two Months

My journey with Rust 😍

It’s been two months already! The discussion took off with a discussion on lifetime errors, deciding which one is more important than the other and selecting specific cases to deal with.

loop {

//Iteration I

The Perfect Error

The hunt to find the simplest and most basic error message to start with began. Considering various common lifetime errors, we decided to go ahead with the one above. We had discussions on the region inferencing in the Rust Compiler to understand anonymous regions(lifetimes), in particular the RegionResolution Error.

fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
    if x > y { x } else { y }
}

We picked up an example with one anonymous and one named region.

The Perfect Error Message

Finding the perfect example to start off wasn’t enough. A lot of time went in discussing the final looks of the error message. Lifetimes are a major reason why the beginners of Rust struggle at the start and our whole effort was directed at changing that experience.

fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
                       - consider changing the type of `y` to `&'a i32`
if x > y { x } else { y }
                      ^ this reference must have lifetime 'a
}

Write Code

Well, when you know what is the expected output, coding becomes a bit easier. This was the first time I had to deep dive into the region_inference related error_reporting modules in the Rust Compiler. Walking the hir map to search for the anonymous region and replacing it by the named region using Typefolders resulted in the above error message.

Write Better Code

The code review has been an empowering experience for me. I have previously worked on huge codebases for my internship but this was something new. As a beginner in open source, a community review structure has given me a broader perspective on the programming principles of Rust.

PR Merged ❤

Run the example here.

//Iteration II

The Next Perfect Example

E0623 considers the cases like above where both the regions are anonymous.

fn foo(x: &mut Vec<&u8>, y: &u8) {
x.push(y);
}

The Next Perfect Error Message

11 | fn foo(x: &mut Vec<&u8>, y: &u8) {
| --- --- these references are not declared with the same lifetime...
12 | x.push(y);
| ^ ...but data from `y` flows into `x` here

error: aborting due to previous error

The hir::Ty is extracted for both the regions using a NestedTypeVisitor . NestedTypeVisitor.found_type gives us the required region i.e. &<u8> and Vec<&u8> for the case above. For the case of structs, we have the following error message( More on this is an upcoming post).

| fn foo(mut x: Vec<Ref<T>>,
| ---
| y: Ref<T>)
| --- these two structs are not declared with the same lifetime ...
|{
| x.push(y);
| ^ ... but data flows from `y` into `x` here
| }
help: consider changing the signature to:
| fn foo<'a>(mut x: Vec<'a, Ref<T>>, y: Ref<'a, T>)

Write Code

The changes for the above error message have been merged. The changes for structs are not yet in PR phase.

}

And the cycle continues…

The changes for E0621 and E0623 have been successfully merged 😃.

Show your support

Clapping shows how much you appreciated GeekyTwoShoes11’s story.