]> git.lizzy.rs Git - rust.git/blob - guide.md
start completions walkthrough
[rust.git] / guide.md
1 # Guide to rust-analyzer
2
3 ## About the guide
4
5 This guide describes the current start of the rust-analyzer as of 2019-01-20
6 (commit hash guide-2019-01). Its purpose is to
7 document various problems and architectural solutions related to the problem of
8 building IDE-first compiler.
9
10 ## The big picture
11
12 On the highest possible level, rust analyzer is a stateful component. Client may
13 apply changes to the analyzer (new contents of `foo.rs` file is "fn main() {}")
14 and it may ask semantic questions about the current state (what is the
15 definition of the identifier with offset 92 in file `bar.rs`?). Two important
16 properties hold:
17
18 * Analyzer does not do any IO. It starts in an empty state and all input data is
19   provided via `apply_change` API.
20
21 * Only queries about the current state are supported. One can, of course,
22   simulate undo and redo by keeping log of changes and inverse-changes.
23
24 ## IDE API
25
26 To see this big picture, let's take a look at the [`AnalysisHost`] and
27 [`Analysis`] pair of types. `AnalysisHost` has three methods:
28
29 * `default` for creating an empty analysis
30 * `apply_change(&mut self)` to make changes (this is how you get from an empty
31   state to something interesting)
32 * `analysis(&self)` to get an instance of `Analysis`
33
34 `Analysis` has a ton of methods for IDEs, like `goto_definition`, or
35 `completions`. Both inputs and outputs of `Analysis`' methods are formulated in
36 terms of files and offsets, and **not** in terms of Rust concepts like structs,
37 traits, etc. The "typed" API with Rust specific types is slightly lower in the
38 stack, we'll talk about it later.
39
40 [`AnalysisHost`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L265-L284
41 [`Analysis`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L291-L478
42
43 The reason for `Analysis` and `AnalysisHost` separation is that we want apply
44 changes "uniquely", but we might want to fork an `Analysis` and send it to
45 another thread for background processing. That is, there is only a single
46 `AnalysisHost`, but there may be several (equivalent) `Analysis`.
47
48 Note that all of the `Analysis` API return `Cancelable<T>`. This is required to
49 be responsive in IDE setting. Sometimes a long-running query is being computed
50 and the user types something in the editor and asks for completion. In this
51 case, we cancel the long-running computation (so it returns `Err(Canceled)`),
52 apply the change and execute request for completion. We never use stale data to
53 answer requests. Under the cover, `AnalysisHost` "remembers" all outstanding
54 `Analysis` instances. `AnalysisHost::apply_change` method cancels all
55 `Analysis`es, blocks until of them are `Dropped` and then applies change
56 in-place. This is the familiar to rustaceans read-write lock interior
57 mutability.
58
59 Next, lets talk about what are inputs to the Analysis, precisely.
60
61 ## Inputs
62
63 Rust Analyzer never does any IO itself, all inputs get passed explicitly via
64 `AnalysisHost::apply_change` method, which accepts a single argument:
65 `AnalysisChange`. [`AnalysisChange`] is a builder for a single change
66 "transaction", so it suffices to study its methods to understand all of the
67 input data.
68
69 [`AnalysisChange`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L119-L167
70
71 The `(add|change|remove)_file` methods control the set of the input files, where
72 each file has an integer id (`FileId`, picked by the client), text (`String`)
73 and a filesystem path. Paths are tricky, they'll be explained in source roots
74 section, together with `add_root` method. `add_library` method allows to add a
75 group of files which are assumed to rarely change. It's mostly an optimization
76 and does not change fundamental picture.
77
78 `set_crate_graph` method allows to control how the input files are partitioned
79 into compilation unites -- crates. It also controls (in theory, not implemented
80 yet) `cfg` flags. `CrateGraph` is a directed acyclic graph of crates. Each crate
81 has a root `FileId`, a set of active `cfg` flags and a set of dependencies. Each
82 dependency is a pair of a crate and a name. It is possible to have two crates
83 with the same root `FileId` but different `cfg`-flags/dependencies. This model
84 is lower than Cargo's model of packages: each Cargo package consists of several
85 targets, each of which is a separate crate (or several crates, if you try
86 different feature combinations).
87
88 Procedural macros should become inputs as well, but currently they are not
89 supported. Procedural macro will be a black box `Box<dyn Fn(TokenStream) -> TokenStream>`
90 function, and will be inserted into the crate graph just like dependencies.
91
92 Soon we'll talk how we build an LSP server on top of `Analysis`, but first,
93 let's deal with that paths issue.
94
95
96 ## Source roots (aka filesystems are horrible)
97
98 This is a non-essential section, feel free to skip.
99
100 The previous section said that the file system path is an attribute of a file,
101 but this is not a whole truth. Making it an absolute `PathBuf` will be bad for
102 several reasons. First, file-systems are full of (platform-dependent) edge cases:
103
104 * it's hard (requires a syscall) to decide if two paths are equivalent
105 * some file-systems are case-sensitive
106 * paths are not necessary UTF-8
107 * symlinks can form cycles
108
109 Second, this might hurt reproducibility and hermeticity of builds. In theory,
110 moving a project from `/foo/bar/my-project` to `/spam/eggs/my-project` should
111 not change a bit in the output. However, if absolute path is a part of the
112 input, it is at least in theory observable, and *could* affect the output.
113
114 Yet another problem is that we really-really want to avoid doing IO, but with
115 Rust the set of "input" files is not necessary known up-front. In theory, you
116 can have `#[path="/dev/random"] mod foo;`.
117
118 To solve (or explicitly refuse to solve) these problems rust analyzer uses the
119 concept of source root. Roughly speaking, source roots is a contents of a
120 directory on a file systems, like `/home/matklad/projects/rustraytracer/**.rs`.
121
122 More precisely, all files (`FileId`s) are partitioned into disjoint
123 `SourceRoot`s. Each file has a relative utf-8 path within the `SourceRoot`.
124 `SourceRoot` has an identity (integer id). Crucially, the root path of the
125 source root itself is unknown to the analyzer: client is supposed to maintain a
126 mapping between SourceRoot ids (which are assigned by the client) and actual
127 `PathBuf`s. `SourceRoot`s give a sane tree model of the file system to the
128 analyzer.
129
130 Note that `mod`, `#[path]` and `include!()` can only reference files from the
131 same source root. It is of course is possible to explicitly add extra files to
132 the source root, even `/dev/random`.
133
134 ## Language Server Protocol
135
136 Now let's see how `Analysis` API is exposed via JSON RPC based LSP protocol. The
137 hard part here is managing changes (which can come either from the file system
138 or from the editor) and concurrency (we want to spawn background jobs for things
139 like syntax highlighting). We use the event loop pattern to manage the zoo, and
140 the loop is the [`main_loop_inner`] function. The [`main_loop`] does a one-time
141 initialization and tearing down of the resources.
142
143 [`main_loop`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L51-L110
144 [`main_loop_inner`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L156-L258
145
146
147 Let's walk through a typical analyzer session!
148
149 First, we need to figure out what to analyze. To do this, we run `cargo
150 metadata` to learn about Cargo packages for current workspace and dependencies,
151 and we run `rustc --print sysroot` and scan sysroot to learn about crates like
152 `std`. Currently we load this configuration once at the start of the server, but
153 it should be possible to dynamically reconfigure it later without restart.
154
155 [main_loop.rs#L62-L70](https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L62-L70)
156
157 The [`ProjectModel`] we get after this step is very Cargo and sysroot specific,
158 it needs to be lowered to get the input in the form of `AnalysisChange`. This
159 happens in [`ServerWorldState::new`] method. Specifically
160
161 * Create a `SourceRoot` for each Cargo package and sysroot.
162 * Schedule a file system scan of the roots.
163 * Create an analyzer's `Crate` for each Cargo **target** and sysroot crate.
164 * Setup dependencies between the crates.
165
166 [`ProjectModel`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/project_model.rs#L16-L20
167 [`ServerWorldState::new`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/server_world.rs#L38-L160
168
169 The results of the scan (which may take a while) will be processed in the body
170 of the main loop, just like any other change. Here's where we handle
171
172 * [File system changes](https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L194)
173 * [Changes from the editor](https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L377)
174
175 After a single loop's turn, we group them into one `AnalysisChange` and
176 [apply] it. This always happens on the main thread and blocks the loop.
177
178 [apply]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/server_world.rs#L216
179
180 To handle requests, like ["goto definition"], we create an instance of the
181 `Analysis` and [`schedule`] the task (which consumes `Analysis`) onto
182 threadpool. [The task] calls the corresponding `Analysis` method, while
183 massaging the types into the LSP representation. Keep in mind that if we are
184 executing "goto definition" on the threadpool and a new change comes in, the
185 task will be canceled as soon as the main loop calls `apply_change` on the
186 `AnalysisHost`.
187
188 ["goto definition"]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/server_world.rs#L216
189 [`schedule`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L426-L455
190 [The task]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop/handlers.rs#L205-L223
191
192 This concludes the overview of the analyzer's programing *interface*. Next, lets
193 dig into the implementation!
194
195 ## Salsa
196
197 The most straightforward way to implement "apply change, get analysis, repeat"
198 API would be to maintain the input state and to compute all possible analysis
199 information from scratch after every change. This works, but scales poorly with
200 the size of the project. To make this fast, we need to take advantage of the
201 fact that most of the changes are small, and that analysis results are unlikely
202 to change significantly between invocations.
203
204 To do this we use [salsa]: a framework for incremental on-demand computation.
205 You can skip the rest of the section if you are familiar with rustc red-green
206 algorithm.
207
208 [salsa]: https://github.com/salsa-rs/salsa
209
210 It's better to refer to salsa's docs to learn about it. Here's a small excerpt:
211
212 The key idea of salsa is that you define your program as a set of queries. Every
213 query is used like function K -> V that maps from some key of type K to a value
214 of type V. Queries come in two basic varieties:
215
216 * **Inputs**: the base inputs to your system. You can change these whenever you
217   like.
218
219 * **Functions**: pure functions (no side effects) that transform your inputs
220   into other values. The results of queries is memoized to avoid recomputing
221   them a lot. When you make changes to the inputs, we'll figure out (fairlywe
222   intelligently) when we can re-use these memoized values and when we have we
223   recompute them.
224
225
226 For further discussion, its important to understand one bit of "fairly
227 intelligently". Suppose we have to functions, `f1` and `f2`, and one input,we
228 We call `f1(X)` which in turn calls `f2(Y)` which inspects `i(Z)`. `i(Z)`
229 returns some value `V1`, `f2` uses that and returns `R1`, `f1` uses that anwe
230 returns `O`. Now, let's change `i` at `Z` to `V2` from `V1` and try to compwe
231 `f1(X)` again. Because `f1(X)` (transitively) depends on `i(Z)`, we can't jwe
232 reuse its value as is. However, if `f2(Y)` is *still* equal to `R1` (despitwe
233 `i`'s change), we, in fact, *can* reuse `O` as result of `f1(X)`. And that'we
234 salsa works: it recomputes results in *reverse* order, starting from inputswe
235 progressing towards outputs, stopping as soon as it sees an intermediate vawe
236 that hasn't changed.
237
238 ## Salsa Input Queries
239
240 All analyzer information is stored in a salsa database. `Analysis` and
241 `AnalysisHost` types are newtype wrappers for [`RootDatabase`] -- a salsa
242 database.
243
244 [`RootDatabase`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/db.rs#L88-L134
245
246 Salsa input queries are defined in [`FilesDatabase`] (which is a part of
247 `RootDatabase`). They closely mirror the familiar `AnalysisChange` structure:
248 indeed, what `apply_change` does is it sets the values of input queries.
249
250 [`FilesDatabase`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_db/src/input.rs#L150-L174
251
252 ## From text to semantic model
253
254 The bulk of the rust-analyzer is transforming input text into semantic model of
255 Rust code: a web of entities like modules, structs, functions and traits.
256
257 An important fact to realize is that (unlike most other languages like C# or
258 Java) there isn't a one-to-one mapping between source code and semantic model. A
259 single function definition in the source code might result in several semantic
260 functions: for example, the same source file might be included as a module into
261 several crate, or a single "crate" might be present in the compilation DAG
262 several times, with different sets of `cfg`s enabled. The IDE-specific task of
263 mapping source code position into semantic model is inherently imprecise for
264 this reason, and is handled by the [`source_binder`].
265
266 [`source_binder`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/source_binder.rs
267
268 The semantic interface is declared in [`code_model_api`] module. Each entity is
269 identified by integer id and has a bunch of methods which take a salsa database
270 as an argument and returns other entities (which are ids). Internally, this
271 methods invoke various queries on the database to build the model on demand.
272 Here's [the list of queries].
273
274 [`code_model_api`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/code_model_api.rs
275 [the list of queries]: https://github.com/rust-analyzer/rust-analyzer/blob/7e84440e25e19529e4ff8a66e521d1b06349c6ec/crates/ra_hir/src/db.rs#L20-L106
276
277 The first step of building the model is parsing the source code.
278
279 ## Syntax trees
280
281 An important property of the Rust language is that each file can be parsed in
282 isolation. Unlike, say, `C++`, an `include` can't change the meaning of the
283 syntax. For this reason, Rust analyzer can build a syntax tree for each "source
284 file", which could then be reused by several semantic models if this file
285 happens to be a part of several crates.
286
287 Rust analyzer uses a similar representation of syntax trees to that of `Roslyn`
288 and Swift's new [libsyntax]. Swift's docs give an excellent overview of the
289 approach, so I skip this part here and instead outline the main characteristics
290 of the syntax trees:
291
292 * Syntax trees are fully lossless. Converting **any** text to a syntax tree and
293   back is a total identity function. All whitespace and comments are explicitly
294   represented in the tree.
295
296 * Syntax nodes have generic `(next|previous)_sibling`, `parent`,
297   `(first|last)_child` functions. You can get from any one node to any other
298   node in the file using only these functions.
299
300 * Syntax nodes know their range (start offset and length) in the file.
301
302 * Syntax nodes share the ownership of their syntax tree: if you keep a reference
303   to a single function, the whole enclosing file is alive.
304
305 * Syntax trees are immutable and the cost of replacing the subtree is
306   proportional to the depth of the subtree. Read Swift's docs to learn how
307   immutable + parent pointers + cheap modification is possible.
308
309 * Syntax trees are build on best-effort basis. All accessor methods return
310   `Option`s. The tree for `fn foo` will contain a function declaration with
311   `None` for parameter list and body.
312
313 * Syntax trees do not know the file they are build from, they only know about
314   the text.
315
316 The implementation is based on the generic [rowan] crate on top of which a
317 [rust-specific] AST is generated.
318
319 [libsyntax]: https://github.com/apple/swift/tree/5e2c815edfd758f9b1309ce07bfc01c4bc20ec23/lib/Syntax
320 [rowan]: https://github.com/rust-analyzer/rowan/tree/100a36dc820eb393b74abe0d20ddf99077b61f88
321 [rust-specific]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_syntax/src/ast/generated.rs
322
323 The next step in constructing the semantic model is ...
324
325 ## Building a Module Tree
326
327 The algorithm for building a tree of modules is to start with a crate root
328 (remember, each `Crate` from a `CrateGraph` has a `FileId`), collect all mod
329 declarations and recursively process child modules. This is handled by the
330 [`module_tree_query`], with a two slight variations.
331
332 [`module_tree_query`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/module_tree.rs#L116-L123
333
334 First, rust analyzer builds a module tree for all crates in a source root
335 simultaneously. The main reason for this is historical (`module_tree` predates
336 `CrateGraph`), but this approach also allows to account for files which are not
337 part of any crate. That is, if you create a file but do not include it as a
338 submodule anywhere, you still get semantic completion, and you get a warning
339 about free-floating module (the actual warning is not implemented yet).
340
341 The second difference is that `module_tree_query` does not *directly* depend on
342 the "parse" query (which is confusingly called `source_file`). Why would calling
343 the parse directly be bad? Suppose the user changes the file slightly, by adding
344 an insignificant whitespace. Adding whitespace changes the parse tree (because
345 it includes whitespace), and that means recomputing the whole module tree.
346
347 We deal with this problem by introducing an intermediate [`submodules_query`].
348 This query processes the syntax tree an extract a set of declared submodule
349 names. Now, changing the whitespace results in `submodules_query` being
350 re-executed for a *single* module, but because the result of this query stays
351 the same, we don't have to re-execute [`module_tree_query`]. In fact, we only
352 need to re-execute it when we add/remove new files or when we change mod
353 declarations.
354
355 [`submodules_query`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/module_tree.rs#L41)
356
357 We store the resulting modules in a `Vec`-based indexed arena. The indices in
358 the arena becomes module ids. And this brings us to the next topic:
359 assigning ids in the general case.
360
361 ## Location Interner pattern
362
363 One way to assign ids is how we've dealt with modules: collect all items into a
364 single array in some specific order and use index in the array as an id. The
365 main drawback of this approach is that ids are not stable: adding a new item can
366 shift ids of all other items. This works for modules, because adding a module is
367 a comparatively rare operation, but would be less convenient for, for example
368 functions.
369
370 Another solution here is positional ids: we can identify a function as "the
371 function with name `foo` in a ModuleId(92) module". Such locations are stable:
372 adding a new function to the module (unless it is also named `foo`) does not
373 change the location. However, such "id" ceases to be a `Copy` integer and in
374 general can become pretty large if we account for nesting (third parameter of
375 the foo function of the bar impl in the baz module).
376
377 [`LocationInterner`] allows us to combine benefits of positional and numeric
378 ids. It is a bidirectional append only map between locations and consecutive
379 integers which can "intern" a location and return an integer id back. Salsa
380 database we use includes a couple of [interners]. How to "garbage collect"
381 unused locations is an open question.
382
383 [`LocationInterner`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_db/src/loc2id.rs#L65-L71
384 [interners]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/db.rs#L22-L23
385
386 For example, we use `LocationInterner` to assign ids to defs: functions,
387 structs, enums, etc. The location, [`DefLoc`] contains two bits of information:
388
389 * the id of the module which contains the def,
390 * the id of the specific item in the modules source code.
391
392 We "could" use a text offset for location a particular item, but that would play
393 badly with salsa: offsets change after edits. So, as a rule of thumb, we avoid
394 using offsets, text ranges or syntax trees as keys and values for queries. What
395 we do instead is we store "index" of the item among all of the items of a file
396 (so, a positional based ID, but localized to a single file).
397
398 [`DefLoc`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L127-L139
399
400 One thing we've glossed over for the time being is support for macros. We have
401 only proof of concept handling of macros at the moment, but they are extremely
402 interesting from "assigning ids" perspective.
403
404 ## Macros and recursive locations
405
406 The tricky bit about macros is that they effectively create new source files.
407 While we can use `FileId`s to refer to original files, we can't just assign them
408 willy-nilly to the pseudo files of macro expansion. Instead, we use a special
409 ID, [`HirFileId`] to refer to either a usual file or a macro-generated file:
410
411 ```rust
412 enum HirFileId {
413     FileId(FileId),
414     Macro(MacroCallId),
415 }
416 ```
417
418 `MacroCallId` is an interned ID that specifies a particular macro invocation.
419 Its `MacroCallLoc` contains:
420
421 * `ModuleId` of the containing module
422 * `HirFileId` of the containing file or pseudo file
423 * an index of this particular macro invocation in this file (positional id
424   again).
425
426 Note how `HirFileId` is defined in terms of `MacroCallLoc` which is defined in
427 terms of `HirFileId`! This does not recur infinitely though: any chain of
428 `HirFileId`s bottoms out in `HirFileId::FileId`, that is, some source file
429 actually written by the user.
430
431 [`HirFileId`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L18-L125
432
433 Now that we understand how to identify a definition, in a source or in a
434 macro-generated file, we can discuss name resolution a bit.
435
436 ## Name resolution
437
438 Name resolution faces the same problem as the module tree: if we look at the
439 syntax tree directly, we'll have to recompute name resolution after every
440 modification. The solution to the problem is the same: we [lower] source code of
441 each module into a position-independent representation which does not change if
442 we modify bodies of the items. After that we [loop] resolving all imports until
443 we've reached a fixed point.
444
445 [lower]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L113-L117
446 [loop]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L113-L117
447
448 And, given all our preparation with ids and position-independent representation,
449 it is satisfying to [test] that typing inside function body does not invalidate
450 name resolution results.
451
452 [test]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/tests.rs#L376
453
454 An interesting fact about name resolution is that it "erases" all of
455 intermediate paths from the imports: in the end, we know which items are defined
456 and which items are imported in each module, but, if the import was `use
457 foo::bar::baz`, we deliberately forget what modules `foo` and `bar` resolve to.
458
459 To serve "goto definition" requests on intermediate segments we need this info
460 in IDE. Luckily, we need it only for a tiny fraction of imports, so we just ask
461 the module explicitly, "where does `foo::bar` path resolve to?". This is a
462 general pattern: we try to compute the minimal possible amount of information
463 during analysis while allowing IDE to ask for additional specific bits.
464
465 Name resolution is also a good place to introduce another salsa pattern used
466 throughout the analyzer:
467
468 ## Source Map pattern
469
470 Due to an obscure edge case in completion, IDE needs to know the syntax node of
471 an use statement which imported the given completion candidate. We can't just
472 store the syntax node as a part of name resolution: this will break
473 incrementality, due to the fact that syntax changes after every file
474 modification.
475
476 We solve this problem during the lowering step of name resolution. Lowering
477 query actually produces a *pair* of outputs: `LoweredModule` and [`SourceMap`].
478 `LoweredModule` module contains [imports], but in a position-independent form.
479 The `SourceMap` contains a mapping from position-independent imports to
480 (position-dependent) syntax nodes.
481
482 The result of this basic lowering query changes after every modification. But
483 there's an intermediate [projection query] which returns only the first
484 position-independent part of the lowering. The result of this query is stable.
485 Naturally, name resolution [uses] this stable projection query.
486
487 [imports]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59
488 [`SourceMap`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59
489 [projection query]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L97-L103
490 [uses]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/query_definitions.rs#L49
491
492 ## Type inference
493
494 First of all, implementation of type inference in rust analyzer was spearheaded
495 by [@flodiebold]. [#327] was an awesome Christmas present, thank you, Florian!
496
497 Type inference runs on per-function granularity and uses the patterns we've
498 discussed previously.
499
500 First, we [lower ast] of function body into a position-independent
501 representation. In this representation, each expression is assigned a
502 [positional id]. Alongside the lowered expression, [a source map] is produced,
503 which maps between expression ids and original syntax. This lowering step also
504 deals with "incomplete" source trees by replacing missing expressions by an
505 explicit `Missing` expression.
506
507 Given the lower body of the function, we can now run [type inference] and
508 construct a mapping from `ExprId`s to types.
509
510 [@flodiebold]: https://github.com/flodiebold
511 [#327]: https://github.com/rust-analyzer/rust-analyzer/pull/327
512 [lower ast]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs
513 [positional id]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs#L13-L15
514 [a source map]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs#L41-L44
515 [type-inference]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ty.rs#L1208-L1223
516
517 ## Tying it all together: completion
518
519 To conclude the overview of the rust analyzer, let's trace the request for
520 (type-inference powered!) code completion!
521
522 We start by [receiving a message] from the language client. We decode the
523 message as a request for completion and [schedule it on the threadpool]. This is
524 the place where we [catch] canceled error if, immediately after completion, the
525 client sends some modification.
526
527 [receiving a message]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L203
528 [schedule it on the threadpool]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L428
529 [catch]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L436-L442