diff options
-rw-r--r-- | guide.md | 57 |
1 files changed, 57 insertions, 0 deletions
@@ -426,8 +426,65 @@ actually written by the user. | |||
426 | 426 | ||
427 | [`HirFileId`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L18-L125 | 427 | [`HirFileId`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L18-L125 |
428 | 428 | ||
429 | Now that we understand how to identify a definition, in a source or in a | ||
430 | macro-generated file, we can discuss name resolution a bit. | ||
431 | |||
429 | ## Name resolution | 432 | ## Name resolution |
430 | 433 | ||
434 | Name resolution faces the same problem as the module tree: if we look at the | ||
435 | syntax tree directly, we'll have to recompute name resolution after every | ||
436 | modification. The solution to the problem is the same: we [lower] source code of | ||
437 | each module into a position-independent representation which does not change if | ||
438 | we modify bodies of the items. After that we [loop] resolving all imports until | ||
439 | we've reached a fixed point. | ||
440 | |||
441 | [lower]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L113-L117 | ||
442 | [loop]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L113-L117 | ||
443 | |||
444 | And, given all our preparation with ids and position-independent representation, | ||
445 | it is satisfying to [test] that typing inside function body does not invalidate | ||
446 | name resolution results. | ||
447 | |||
448 | [test]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/tests.rs#L376 | ||
449 | |||
450 | An interesting fact about name resolution is that it "erases" all of | ||
451 | intermediate paths from the imports: in the end, we know which items are defined | ||
452 | and which items are imported in each module, but, if the import was `use | ||
453 | foo::bar::baz`, we deliberately forget what modules `foo` and `bar` resolve to. | ||
454 | |||
455 | To serve "goto definition" requests on intermediate segments we need this info | ||
456 | in IDE. Luckily, we need it only for a tiny fraction of imports, so we just ask | ||
457 | the module explicitly, "where does `foo::bar` path resolve to?". This is a | ||
458 | general pattern: we try to compute the minimal possible amount of information | ||
459 | during analysis while allowing IDE to ask for additional specific bits. | ||
460 | |||
461 | Name resolution is also a good place to introduce another salsa pattern used | ||
462 | throughout the analyzer: | ||
463 | |||
431 | ## Source Map pattern | 464 | ## Source Map pattern |
432 | 465 | ||
466 | Due to an obscure edge case in completion, IDE needs to know the syntax node of | ||
467 | an use statement which imported the given completion candidate. We can't just | ||
468 | store the syntax node as a part of name resolution: this will break | ||
469 | incrementality, due to the fact that syntax changes after every file | ||
470 | modification. | ||
471 | |||
472 | We solve this problem during the lowering step of name resolution. Lowering | ||
473 | query actually produces a *pair* of outputs: `LoweredModule` and [`SourceMap`]. | ||
474 | `LoweredModule` module contains [imports], but in a position-independent form. | ||
475 | The `SourceMap` contains a mapping from position-independent imports to | ||
476 | (position-dependent) syntax nodes. | ||
477 | |||
478 | The result of this basic lowering query changes after every modification. But | ||
479 | there's an intermediate [projection query] which returns only the first | ||
480 | position-independent part of the lowering. The result of this query is stable. | ||
481 | Naturally, name resolution [uses] this stable projection query. | ||
482 | |||
483 | [imports]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59 | ||
484 | [`SourceMap`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59 | ||
485 | [projection query]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L97-L103 | ||
486 | [uses]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/query_definitions.rs#L49 | ||
487 | |||
488 | ## Type inference | ||
489 | |||
433 | ## Tying it all together: completion | 490 | ## Tying it all together: completion |