Once a Rustacean, always a Rustacean.

This story tracks the beginning of my journey with Mozilla, where I worked on making error messages for lifetime conflicts user-friendly and simple but precise for the Rust Programming Language.

The first time I showed interest in making a contribution to Rust, my mentor Niko Matsakis scheduled a video chat with me and explained to me about the project which titled was making an Unsafe code linting tool for Rust. He then presented a few code snippets to help me understand where the problem lay and drew similarities with C++, since I was new to Rust then. As much as I was nervous, I loved the idea of developing the unsafe linting tool. Then we went on to discuss how I should proceed with my first contribution and we zeroed in on Rayon, a parallel data library for Rust.

My first contribution was this

The reason we went ahead with Rayon was because the linting tool would be tested with Rayon, as it had a huge amount of unsafe code. I wrote unit tests for the collect consumer, closing an existing issue —

and successively made my second contribution too

The happiness you feel when you make your very first PR issue is 💓

This helped me understand how the collect consumer worked and I got to see examples of unsafe code.

Going ahead, my mentor searched for beginner level issues, keeping in mind that the more I get used to Rust, the better and decided that I should fix issues in the Rust Compiler itself. My first reaction must have been 😯 as I was quite new to open source and my first impression of making a contribution to the compiler itself meant something difficult.

I remember discussing with a friend that Rust is my first open source Contribution and she was like you’re very lucky ☺

I’ve heard of contribution stories going wrong. Not that it ever mattered but I’ve felt so loved by the community that I’m really grateful for the experience.

On the rust compiler, I was to work with the region inferencing part of the compiler and the first issue was to fix an existing error message.

issue on let suggestions

and the PR link for the same.

I then worked on the same issue, introducing another change in the error message

Now came the time when I had to build the compiler locally, running ./x.py build — — incremental and ./x.py test src/test/ui constantly, often having my share of struggles with the borrow checker, but nothing short of a learning experience. I followed the mentoring instructions written by my mentor and wrote my first few lines of proper Rust code. Over time, I’ve grown fond of the build commands :p.

I remember talking to Niko Matsakis and he suggested picking up the harder of the two issues that I was planning to work on and that decision helped me throughout the internship. It familiarized me with building the compiler, running the test suite and running the compiler locally on different examples to see how the code change was reflecting from the user perspective. So when later, he proposed the idea of working on lifetime errors instead of the linting tool, I took an instant liking to it. The major reason he explained was that this would have more of an impact in less amount of time. The second important reason was that I would get to explore a part of the compiler very few apart from the team are familiar with i.e. the region inferencing part. Then based on the feedback, we will be further modifying the errors more( sounds fun?). The linter would be somewhat on the lines of Clippy. The lifetime error work would be something different. As easy as it may sound, designing the message itself needed effort. You have to be simple yet precise. That’s difficult. It’s difficult when you probably want to explain everything in paragraphs so that the user experience is better but then you need to be careful too, as you shouldn’t give them too much information that they understand nothing out of it. The challenge was to think as a user. A code of hundred plus lines and what that did was just change the error message for a few cases. This is how the project title changed.

I started off a bit early, the excitement was too difficult to contain :p and there was plenty of free time. We looked at a few common examples and tried to understand how lifetimes work. Then he walked me through a bit of the error reporting code, pointing out functions being used and the types of parameters being passed and other important declarations. We picked up the simplest example, discussing it’s features in depth and then figuring out all the cases it covered.

What I was to deal with was anonymous lifetimes i.e. missing lifetime parameters. Lifetimes or regions, being among the few things that confused the Rust users, we safely assumed that if it was missing the lifetime declarations in the function or trait declarations unlike the fault being in the code itself.

That’s how we started. A new error message for functions with one named parameter and one anonymous parameter. E0621. There is a systematic procedure you follow for the same. Once you fix the error message, you need to run the test suite. You also need to add an explanation in the diagnostics.rs file which is like registering the error code. You also need to add new ui tests (show the output) and compile-fail tests. Now it might sound simple but it wasn’t.

I had to understand the way Rust Compiler defines an error, to be specific, RegionResolution Errors. I had to understand the report_region_errors() method. I have limited myself to working with only ConcreteFailure errors throughout. My first blog post speaks about it. This post speaks on how we planned to extend it for traits and impls, keeping it on hold for anonymous regions in self and return type. The most challenging part here was to replace the anonymous region with the named region here

consider changing the type of `y` to `&’a i32`

I did it using TypeFolders.

Here is the merged PR

https://github.com/rust-lang/rust/pull/42669

Talking of merges, the happiness when your code gets merged with the master branch is amazing : dancer

Moving on from there, I went a few steps ahead, trying to handle conflicts where both the regions are anonymous or what we call the anon_anon conflict. It was more difficult here, there were too many cases and error design itself kept changing due to the feedback we got.

Here is the link to the PR for handling it in references.

https://github.com/rust-lang/rust/pull/43298

The error message was later changed as follows

https://github.com/rust-lang/rust/pull/43541

Later, I extended it to Structs.

https://github.com/rust-lang/rust/pull/43700

The code needed a lot of testing as a few cases were breaking. The code reviews emphasised on the need to write cleaner code.

Currently, I’m having ongoing PRs which are to extend E0623 to named conflicts(blog on this later) and also to cover return types and self.

I’ve planned so much on how to write this post, because there is too much to write . I doubt I will do justice to it but here is my effort. Working with Rust is like the introductory hello world program for me. It’s my first exploration of open source and community contribution. It’s immense growth and love. It’s learning and satisfaction of giving back to a community that’s given you love.

I’ve got the opportunity to work with a language compiler and learn the language, understand it better via contributions. Usually that’s something that works the other way around. You learn the language before you go around digging into the compiler. I’ve had the opportunity to make error messages better for Rust users, of something that I had initial struggles with i.e. the lifetime errors. I’ve got to be the consumer and the producer both. My initial hesitation on learning a new language is now replaced with a curiosity to learn more about Rust every single day.

A huge thank you to Outreachy for organizing this amazing programme and to Sarah Sharp and all the other outreachy admins. A big thank you to Mozilla , Elizabeth Noonan and Larissa Shapiro for making this possible ☺. Thank you Niko Matsakis for being the most amazing mentor anyone could have ever asked for, right from being available to answer my silliest doubts on let and if let to helping out with understanding, writing code and reviewing it, and having an example ready on almost every topic I had doubts with, these three months have been fun to work with you and I’m sure I’m going to continue to be in touch ☺. I’ve been fortunate enough to have got to interact with a few of the Rust core team members, Niko Matsakis , a huge thank you to Ariel Ben-Yehuda (Rust Compiler Team) and Esteban Kuber for reviewing my code and being ever ready to help, Eduard-Mihai Burtescu (Rust Compiler Team) for being a regular at answering my queries on IRC and Guillaume Gomez and Jonathan Turner(Dev tools team) for their reviews and comments. Last but not the least, thank you Gitter : 💓. For reasons unexplainable, I’ve preferred Gitter more over Slack and IRC.

What I’ve learned ?

Deep dive, no first impressions.

How much ever difficult something looks, you can’t really gauge the level of difficulty until you get your hands real dirty with the code and try to experiment a bit. Logs helped me do that, to understand where I was going wrong and what the code was doing. So leap of faith.

Patience

There are days when you feel like productivity seems to be a far away dream. I’ve felt sad looking at a build fail when I know it’s supposed to work fine, I’ve spent my initial days staring at a GitHub pull request, searching for the green tick that often eluded me at the start ( stopped doing that now ;) ) and felt gloomy. Take a short break. A walk maybe. Come back afresh to realize it’s something silly and get it working. The joy that came with it was much more than what would have been if I got it right the first time. I’ve learnt to be patient with my code.

Learn

Even while I was coding , I kept the side process of learning Rust on too. I’ve been fascinated by what all the language has. Compilers was a course in my third year. It was one of my favorites. The assigned needed us to build a mini compiler for a small subset of C. It was something that interested me then. Never did I think that I would be contributing to a language compiler used by a huge community.

Growth

It’s being a huge learning opportunity for me. I have grown as a programmer and developer. I’ve become more confident and more efficient. Most importantly, I’ve found happiness in what I do. Immense satisfaction of contributing to a growing community.

Small is big

The smallest bug fix has got me back to pondering over programming fundamentals and deeper into advanced concepts.

Confidence

I’ve become pretty fluent in communicating with the other contributors, asking questions when blocked on something, opening up relevant issues on GitHub and trying to be precise with my doubts.

Be better.

A better programmer. A better computer science student. A better learner. A better developer. A better person. Fortunately, working remotely wasn’t much of a problem for me.

Communicate, Ask.

When I asked my mentor if there was a faster way to build stage 1 of the compiler, he suggested using ./x.py build --stage 1 src/libsyntax. Earlier I was building the stage 0 redundantly with the ./x.py build --incremental. Often I’ve asked for help to understand certain concepts and he has given me helpful resources and pointers. This has often made me more efficient and saved a lot of my time.

Spread the spirit

I’ve been lucky to get a chance to explain my work to a fellow contributor eager to work on one of the issues I opened up and I’ve been blogging regularly to spread the spirit ☺

First times

I’ve opened up my first pull request, my first issue, my first community code review and my first technical blog written during this period. There’s always a first time.

Moral : Rust is love

Thank you for being the awesome community that you are @rustlang.

This has been one amazing journey, a journey that’s not going to end so soon ☺

Thanks for being a part of my journey. For any queries and suggestions, leave a comment below.