Satisfy tidy checks
This commit is contained in:
parent
3166fb9d3e
commit
1a5993b9ca
12
src/hir.md
12
src/hir.md
|
|
@ -1,13 +1,13 @@
|
|||
# The HIR
|
||||
|
||||
The HIR – "High-Level Intermediate Representation" – is the primary IR used in
|
||||
most of rustc. It is a compiler-friendly representation of the abstract syntax
|
||||
tree (AST) that is generated after parsing, macro expansion, and name
|
||||
The HIR – "High-Level Intermediate Representation" – is the primary IR used
|
||||
in most of rustc. It is a compiler-friendly representation of the abstract
|
||||
syntax tree (AST) that is generated after parsing, macro expansion, and name
|
||||
resolution (see [Lowering](./lowering.md) for how the HIR is created).
|
||||
Many parts of HIR resemble Rust surface syntax quite closely, with
|
||||
the exception that some of Rust's expression forms have been desugared away. For
|
||||
example, `for` loops are converted into a `loop` and do not appear in the HIR.
|
||||
This makes HIR more amenable to analysis than a normal AST.
|
||||
the exception that some of Rust's expression forms have been desugared away.
|
||||
For example, `for` loops are converted into a `loop` and do not appear in
|
||||
the HIR. This makes HIR more amenable to analysis than a normal AST.
|
||||
|
||||
This chapter covers the main concepts of the HIR.
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ of such structures include but are not limited to
|
|||
* `if let`
|
||||
* Converted to `match`
|
||||
* Universal `impl Trait`
|
||||
* Converted to generic arguments (but with some flags, to know that the user didn't write them)
|
||||
* Converted to generic arguments
|
||||
(but with some flags, to know that the user didn't write them)
|
||||
* Existential `impl Trait`
|
||||
* Converted to a virtual `existential type` declaration
|
||||
|
||||
|
|
@ -34,14 +35,14 @@ sanity checks in `src/librustc/hir/map/hir_id_validator.rs`:
|
|||
which produces both a new `NodeId` as well as automatically lowering it
|
||||
for you so you also get the `HirId`.
|
||||
|
||||
If you are creating new `DefId`s, since each `DefId` needs to have a corresponding
|
||||
`NodeId`, it is adviseable to add these `NodeId`s to the `AST` so you don't have
|
||||
to generate new ones during lowering. This has the advantage of creating a
|
||||
way to find the `DefId` of something via its `NodeId`. If lowering needs this
|
||||
`DefId` in multiple places, you can't generate a new `NodeId` in all those places
|
||||
because you'd also get a new `DefId` then. With a `NodeId` from the `AST` this is
|
||||
not an issue.
|
||||
If you are creating new `DefId`s, since each `DefId` needs to have a
|
||||
corresponding `NodeId`, it is adviseable to add these `NodeId`s to the
|
||||
`AST` so you don't have to generate new ones during lowering. This has
|
||||
the advantage of creating a way to find the `DefId` of something via its
|
||||
`NodeId`. If lowering needs this `DefId` in multiple places, you can't
|
||||
generate a new `NodeId` in all those places because you'd also get a new
|
||||
`DefId` then. With a `NodeId` from the `AST` this is not an issue.
|
||||
|
||||
Having the `NodeId` also allows the `DefCollector` to generate the `DefId`s instead
|
||||
of lowering having to do it on the fly. Centralizing the `DefId` generation in one
|
||||
place makes it easier to refactor and reason about.
|
||||
Having the `NodeId` also allows the `DefCollector` to generate the `DefId`s
|
||||
instead of lowering having to do it on the fly. Centralizing the `DefId`
|
||||
generation in one place makes it easier to refactor and reason about.
|
||||
|
|
@ -36,9 +36,9 @@ hierarchy, it's types vs. values vs. macros.
|
|||
## Scopes and ribs
|
||||
|
||||
A name is visible only in certain area in the source code. This forms a
|
||||
hierarchical structure, but not necessarily a simple one ‒ if one scope is part
|
||||
of another, it doesn't mean the name visible in the outer one is also visible in
|
||||
the inner one, or that it refers to the same thing.
|
||||
hierarchical structure, but not necessarily a simple one ‒ if one scope is
|
||||
part of another, it doesn't mean the name visible in the outer one is also
|
||||
visible in the inner one, or that it refers to the same thing.
|
||||
|
||||
To cope with that, the compiler introduces the concept of Ribs. This is
|
||||
abstraction of a scope. Every time the set of visible names potentially changes,
|
||||
|
|
@ -54,9 +54,9 @@ example:
|
|||
When searching for a name, the stack of ribs is traversed from the innermost
|
||||
outwards. This helps to find the closest meaning of the name (the one not
|
||||
shadowed by anything else). The transition to outer rib may also change the
|
||||
rules what names are usable ‒ if there are nested functions (not closures), the
|
||||
inner one can't access parameters and local bindings of the outer one, even
|
||||
though they should be visible by ordinary scoping rules. An example:
|
||||
rules what names are usable ‒ if there are nested functions (not closures),
|
||||
the inner one can't access parameters and local bindings of the outer one,
|
||||
even though they should be visible by ordinary scoping rules. An example:
|
||||
|
||||
```rust
|
||||
fn do_something<T: Default>(val: T) { // <- New rib in both types and values (1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue