Expand description
§resolve_lang
Name resolution over HIR: every path and bare-identifier pattern of a
hir_lang::Hir is bound to the binder or definition it names, under a
language’s scoping Policy, with diagnostics (did-you-mean included)
for what does not resolve, and a persistent Index of definitions and
references for go-to-definition, find-references, rename, and document
symbols.
§The lazy path
resolve takes a unit and the interner its names came from, and
returns the resolved unit, its diagnostics, and the index:
use hir_lang::{Builder, Expr, Name, Res};
use intern_lang::Interner;
// fn double(n) { n } fn main() { double }
let mut names = Interner::new();
let (n, double) = (Name::new(names.intern("n")), Name::new(names.intern("double")));
let mut b = Builder::new();
let (param, n_binder) = b.local_param(n);
let use_n = b.name_expr(n);
let body = b.block(&[], Some(use_n));
let f = b.func(double, &[param], body);
let use_double = b.name_expr(double);
let main_body = b.block(&[], Some(use_double));
let main = b.func(Name::new(names.intern("main")), &[], main_body);
let root = b.module(None, &[f, main]);
let hir = b.finish(root)?;
let unit = hir.unit();
let res = resolve_lang::resolve(hir, &names)?;
assert!(res.is_clean());
let hir = res.hir(unit).unwrap();
let Expr::Path(p) = *hir.expr(use_n) else { unreachable!() };
assert_eq!(hir.path(p).res, Res::Local(n_binder));
let Expr::Path(p) = *hir.expr(use_double) else { unreachable!() };
assert_eq!(hir.path(p).res, Res::Def(hir.def(hir_lang::Def::Item(f))));Resolver adds a policy, an Env for names outside the unit, and a
Budget; Program resolves several units against each other.
§What resolution guarantees
- Every path of the unit ends in exactly one of: resolved (fully, or a
prefix with the rest left to type-directed resolution, as HIR spec
§3.3 allows); resolved with exactly one access diagnostic (private or
protected);
Res::Errwith exactly one diagnostic; or untouched because it was already resolved (or already an error) on input, or because it is a bare identifier pattern that binds. - Resolutions are written through
Hir::resolve_partial, so the result is a validHir; a resolution hir-lang refuses becomesRes::Errwith a diagnostic instead. - Binders are found with
Hir::lookup_localand the walk’s scope events: the HIR’s scope rules are never re-derived here. - Resolution is deterministic, iterative (no recursion over input), and
bounded: linear in the program apart from glob propagation, inheritance
walks, and suggestions, each capped by the
Budget. - The
Indexis consistent: every reference’s definition lists that reference, and nothing else.
§no_std
The crate needs only alloc. The default std feature is additive.
Structs§
- Budget
- Explicit limits on the work untrusted input can cause.
- Class
Member - One member of a class’s effective member table: its own members and
those its mixins contribute, after
insteadofandasrules. - DefRef
- An opaque handle to a definition in an
Index. - Definition
- One definition.
- Diagnostic
- One problem found while resolving, located in a unit.
- Export
- A name the environment exports: what it resolves to, its kind, and who may see it.
- Index
- The persistent definition/reference index of a resolved program.
- Location
- A place in the source.
- MapEnv
- A ready-made in-memory
Env: roots, a prelude, and members of outside containers, each registered once. - NoEnv
- An environment with nothing in it: every name outside the program is unresolved.
- NsSet
- A set of
Namespaces, as a bit set. - Occurrence
- What
Index::atfound at a position. - Policy
- A language’s complete scoping policy.
- Program
- Several units resolved against each other (Tier 3): the in-memory
multi-unit driver. Each unit may be given a root name, by which every
unit (itself included) can reach its root module as a path’s first
segment (
util::helper,import util). Imports may form cycles across units. - Reference
- One resolved name in a path.
- References
- The references to one definition, in location order: see
Index::references. - Rename
Set - The edits a rename of one definition makes.
- Resolution
- The result of resolving a program: the resolved units, every diagnostic, and the definition/reference index.
- Resolved
Unit - One resolved unit.
- Resolver
- Resolves one unit (Tier 2): a policy, an environment, a budget.
Enums§
- Case
- How a namespace’s table compares names.
- Class
Scope - What code nested in a class can see of the class’s members unqualified.
- DefKind
- What kind of definition a resolution names, as far as scoping cares.
- Diag
Kind - What went wrong, with the data a tool needs to explain or fix it.
- Hoist
- When an item’s name becomes visible in its scope.
- Item
Class - The kinds of named items a policy distinguishes.
- Limit
- Which budget a run exhausted.
- Module
Scope - Whether a nested module sees the names of the modules around it.
- Namespace
- One of the language-level namespaces a name can live in.
- Redefinition
- What two definitions of one name in one scope and namespace mean.
- Reexport
- How an import’s own visibility affects re-export.
- Resolve
Error - Why a resolution run stopped without a result.
- Root
Binding - How a type-relative root (
self::,parent::,static::) binds. - Shadowing
- Whether a binder may reuse a name that is already visible.
- Symbol
Kind - What kind of thing a definition is, for symbol lists and icons.
- Target
- What a definition is, as an identity that survives across units.
Traits§
- Env
- The host’s side of resolution: everything outside the program.
Functions§
- resolve
- Resolves one unit with the default (lexical, Kraken-style) policy and no environment: the lazy path.