Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add introductory section for name resolution chapter #590

Merged
merged 3 commits into from Feb 26, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,6 +1,23 @@
# Name resolution

The name resolution is a two-phase process. In the first phase, which runs
## Basics

In our programs we can refer to variables, types, functions, etc, by giving them
a name. These names are not always unique. For example, take this valid Rust
program:

```rust
type x = u32;
let x: x = 1;
let y: x = 2;
```

How do we know on line 3 whether `x` is a type (u32) or a value (1)? These
conflicts are resolved during name resolution. In this specific case, name
resolution defines that type names and variable names live in separate
namespaces and therefore can co-exist.

The name resolution in Rust is a two-phase process. In the first phase, which runs
during macro expansion, we build a tree of modules and resolve imports. Macro
expansion and name resolution communicate with each other via the `Resolver`
trait, defined in `libsyntax`.
@@ -20,7 +37,7 @@ The name resolution lives in the `librustc_resolve` crate, with the meat in

## Namespaces

Different kind of symbols live in different namespaces ‒ eg. types don't
Different kind of symbols live in different namespaces ‒ e.g. types don't
clash with variables. This usually doesn't happen, because variables start with
lower-case letter while types with upper case one, but this is only a
convention. This is legal Rust code that'll compile (with warnings):
@@ -82,7 +99,7 @@ fn do_something<T: Default>(val: T) { // <- New rib in both types and values (1)

Because the rules for different namespaces are a bit different, each namespace
has its own independent rib stack that is constructed in parallel to the others.
In addition, there's also a rib stack for local labels (eg. names of loops or
In addition, there's also a rib stack for local labels (e.g. names of loops or
blocks), which isn't a full namespace in its own right.

## Overall strategy
@@ -112,7 +129,7 @@ Still, it probably provides useful first guidepost to what happens in there.
following stages of compilation?
* Who calls it and how it is actually used.
* Is it a pass and then the result is only used, or can it be computed
incrementally (eg. for RLS)?
incrementally (e.g. for RLS)?
* The overall strategy description is a bit vague.
* Where does the name `Rib` come from?
* Does this thing have its own tests, or is it tested only as part of some e2e