aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-01-19 19:31:28 +0000
committerAleksey Kladov <[email protected]>2019-01-21 08:27:01 +0000
commit43e7d80ec4ee340636ffabfa2c05ed24a725fa89 (patch)
tree45c563c7c1e71700dbd9683c28e457b2e9f4953e
parentc00059c8224772778586bdf063c76dcbdd04f011 (diff)
source map pattern
-rw-r--r--guide.md57
1 files changed, 57 insertions, 0 deletions
diff --git a/guide.md b/guide.md
index babf58488..d6a9057de 100644
--- a/guide.md
+++ b/guide.md
@@ -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
429Now that we understand how to identify a definition, in a source or in a
430macro-generated file, we can discuss name resolution a bit.
431
429## Name resolution 432## Name resolution
430 433
434Name resolution faces the same problem as the module tree: if we look at the
435syntax tree directly, we'll have to recompute name resolution after every
436modification. The solution to the problem is the same: we [lower] source code of
437each module into a position-independent representation which does not change if
438we modify bodies of the items. After that we [loop] resolving all imports until
439we'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
444And, given all our preparation with ids and position-independent representation,
445it is satisfying to [test] that typing inside function body does not invalidate
446name 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
450An interesting fact about name resolution is that it "erases" all of
451intermediate paths from the imports: in the end, we know which items are defined
452and which items are imported in each module, but, if the import was `use
453foo::bar::baz`, we deliberately forget what modules `foo` and `bar` resolve to.
454
455To serve "goto definition" requests on intermediate segments we need this info
456in IDE. Luckily, we need it only for a tiny fraction of imports, so we just ask
457the module explicitly, "where does `foo::bar` path resolve to?". This is a
458general pattern: we try to compute the minimal possible amount of information
459during analysis while allowing IDE to ask for additional specific bits.
460
461Name resolution is also a good place to introduce another salsa pattern used
462throughout the analyzer:
463
431## Source Map pattern 464## Source Map pattern
432 465
466Due to an obscure edge case in completion, IDE needs to know the syntax node of
467an use statement which imported the given completion candidate. We can't just
468store the syntax node as a part of name resolution: this will break
469incrementality, due to the fact that syntax changes after every file
470modification.
471
472We solve this problem during the lowering step of name resolution. Lowering
473query actually produces a *pair* of outputs: `LoweredModule` and [`SourceMap`].
474`LoweredModule` module contains [imports], but in a position-independent form.
475The `SourceMap` contains a mapping from position-independent imports to
476(position-dependent) syntax nodes.
477
478The result of this basic lowering query changes after every modification. But
479there's an intermediate [projection query] which returns only the first
480position-independent part of the lowering. The result of this query is stable.
481Naturally, 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