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