1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! # 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))));
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```
//!
//! [`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.
extern crate alloc;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
use Hir;
use Lookup;
/// Resolves one unit with the default (lexical, Kraken-style) policy and no
/// environment: the lazy path.
///
/// `names` is the interner the unit's names were interned in; it is read
/// only to compare spellings for did-you-mean suggestions.
///
/// # Errors
///
/// [`ResolveError::BudgetExceeded`] if the unit exceeds the default
/// [`Budget`]. Name errors in the program are diagnostics in the result, not
/// errors.
///
/// # Examples
///
/// ```
/// use hir_lang::{Builder, Name};
/// use intern_lang::Interner;
///
/// let mut names = Interner::new();
/// let mut b = Builder::new();
/// let lenght = b.name_expr(Name::new(names.intern("lenght")));
/// let body = b.block(&[], Some(lenght));
/// let length = b.func(Name::new(names.intern("length")), &[], body);
/// let root = b.module(None, &[length]);
///
/// let res = resolve_lang::resolve(b.finish(root)?, &names)?;
/// let d = &res.diagnostics()[0];
/// assert_eq!(d.message(&names), "cannot find value `lenght` in this scope; did you mean `length`?");
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
/// Compiles and runs the `rust` code blocks in `README.md` and `docs/API.md` as
/// part of `cargo test`, so the published examples cannot drift from the API.
;