Toward Making My First Rust Contribution

caipre · 5 min read

Rust is a modern systems programming language from Mozilla that focuses on memory safety, high performance, and powerful language constructs (ADTs, type inference, pattern matching, lambdas and closures, and lots more). For more details on the language, refer to the Rust homepage. This is the first post in a series that will document my experience making contributions to rustc, the mainline Rust compiler.

As I’m still in the early stages of what will be my first non-trivial contribution, this entry has more questions than answers. Hopefully I’ll be able to write followup posts as I get more comfortable with the Rust codebase. For now, I wanted to write something that might encourage others who are interested in Rust development but are at the same level of unfamiliarity with the codebase and unsure of how to start. So, then, what have I run into so far?

I Have No Idea What I’m Doing!

This is scary! I can’t think of another instance where I’ve been so intimidated to get involved in a project. It’s true that the Rust community is very helpful and welcoming, but the language itself is (initially) unforgiving and I’ve not worked on a compiler before, let alone one as complex as this. I was determined to get involved though, so when an interesting sounding issue showed up in This Week in Rust, I jumped on it even though I had no idea where to start. Since the issue was marked E-mentor, I had the assurance that if I got too far stuck I could reach out for help from someone more knowledgable.

After browsing the code a bit, my list of unknowns became progressively more distressing:

  • How do I map from an AST node back to the code?
  • After the recent error refactoring, are struct_span_{err,warn} still the correct way to prepare error messages (called “diagnostics”)?
  • How can I add a message to a diagnostic without introducing a whole new error?
  • What does this tcx field represent, and where is it defined?
  • Wait, ctags doesn’t work? And racer can’t figure it out either?
  • Erhm, debuggers don’t really work?
  • Where are the docs for internal crates anyway?
  • How do I even build rustc?!

What I’ve Learned So Far

How to build rustc

Answering the last question first, there are currently two build systems for rustc: the standard make based system, and the newer rustbuild system. My understanding is that the former is still the standard method. The latter will eventually replace it but work is still ongoing (as I write this though, I notice that the Rust CI on Travis does --enable-rustbuild).

For my purposes (working on rustc, rather than anything in the standard library), I don’t need to build all the stages of the compiler. Hence, I build my rustc with the following options:

$ ./configure --enable-ccache --enable-debug --enable-clang --enable-fast-make
$ make x86_64-apple-darwin/stage1/bin/rustc

You should replace x86_64-apple-darwin with the appropriate target-triple for your platform. Alternatively, you can make rustc-stage1. I’d love to know whether these are equivalent!

Edit: The two targets are in fact distinct, and the latter is the correct choice. Building just rustc leaves out the standard libraries, which are required when running the various tests (either by make check or directly, eg, ./x86_64-apple-darwin/stage1/bin/rustc ./src/test/compile-fail/...).

About ctags knowing nothing about rustc

My problem was that I was using make TAGS.vi. This target (helpfully?) excludes parsing the internal compiler crates, instead providing tags only for the standard library. So to provide tags for my purposes, I instead run:

$ ctags --options=./src/etc/ctags.rust --recursive -o tags ./src/librustc*

Now that I have ctags, vim-racer, and YouCompleteMe installed, I’m finding it much easier to jump around the codebase and write Rust code naturally. Vim tip: ctrl-o will move to the previous point in the jump stack, ctrl-i will move forward. Since racer doesn’t operate on the tag stack, the usual ctrl-t binding won’t work.

Using debuggers

The most important piece for working with a debugger is ensuring that the --enable-debug flag passed during the build step above. Unlike default builds when using cargo, rustc will default to an optimized build without debugging symbols.

When actually using the debugger, know that support is limited. The build process provides scripts to add rudimentary language support to lldb, but you shouldn’t expect much more than printing local variables or setting breakpoints at lines in the current file. GDB recently announced support for Rust, so hopefully this pain point is no longer an issue.

Finding documentation and getting help

Proper documentation for the internal crates does exist, once you know how to find it. There are README files within many directories that are required reading; these usually provide a detailed overview of the crate or module. A good starting point that covers rustc as a whole is found in the librustc crate.

If no README is present, check for a module doc comment in the crate’s lib.rs. These can be a bit painful to read inline, which is where the internal documentation pages come into play. These are organized just like the standard library docs, meaning they’re incredibly useful to understand how structures relate and what functionality a crate provides. Note though that the search still queries the standard library’s index, so you have to cheat by using your favorite search engine with a filter, eg, mem_categorization site:http://manishearth.github.io/rust-internals-docs/rustc/

If all else fails, hop on IRC. The #rust and #rust-beginners channels are active and the community is welcoming, friendly, and helpful. Setting up an IRC client was a process in itself (I eventually set myself up with weechat), but more than worth it. I’ve now had multiple enlightening conversations with Niko about the issue: initially we believed that the solution lay within the type checker (see conversation in issue thread), but after talking on IRC, Niko realized that a better solution is possible via changes in the borrow checker.

That the Rust project core team offers such mentorship is incredible and speaks highly of the community and of those individuals. Take advantage of it!

Where Am I Now?

I’ve had my name on this issue for far too long. I assigned myself to it back in August, but since then I’ve been distracted by several other projects that were also interesting and maybe a bit less intimidating. A handful of these were Rust projects, which at least helped me to get more comfortable with the language. Now it’s time to buckle down and figure out this issue.