Skip to main content

Crate resolve_lang

Crate resolve_lang 

Source
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::Err with 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 valid Hir; a resolution hir-lang refuses becomes Res::Err with a diagnostic instead.
  • Binders are found with Hir::lookup_local and 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 Index is 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.
ClassMember
One member of a class’s effective member table: its own members and those its mixins contribute, after insteadof and as rules.
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::at found 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.
RenameSet
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.
ResolvedUnit
One resolved unit.
Resolver
Resolves one unit (Tier 2): a policy, an environment, a budget.

Enums§

Case
How a namespace’s table compares names.
ClassScope
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.
DiagKind
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.
ItemClass
The kinds of named items a policy distinguishes.
Limit
Which budget a run exhausted.
ModuleScope
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.
ResolveError
Why a resolution run stopped without a result.
RootBinding
How a type-relative root (self::, parent::, static::) binds.
Shadowing
Whether a binder may reuse a name that is already visible.
SymbolKind
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.