diff options
-rw-r--r-- | guide.md | 30 |
1 files changed, 28 insertions, 2 deletions
@@ -351,11 +351,37 @@ declarations. | |||
351 | [`submodules_query`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/module_tree.rs#L41) | 351 | [`submodules_query`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/module_tree.rs#L41) |
352 | 352 | ||
353 | We store the resulting modules in a `Vec`-based indexed arena. The indices in | 353 | We store the resulting modules in a `Vec`-based indexed arena. The indices in |
354 | the arena becomes module identifiers. | 354 | the arena becomes module ids. And this brings us to the next topic: |
355 | 355 | assigning ids in the general case. | |
356 | 356 | ||
357 | ## Location Interner pattern | 357 | ## Location Interner pattern |
358 | 358 | ||
359 | One way to assign ids is how we've dealt with modules: collect all items into a | ||
360 | single array in some specific order and use index in the array as an id. The | ||
361 | main drawback of this approach is that ids are not stable: adding a new item can | ||
362 | shift ids of all other items. This works for modules, because adding a module is | ||
363 | a comparatively rare operation, but would be less convenient for, for example | ||
364 | functions. | ||
365 | |||
366 | Another solution here is positional ids: we can identify a function as "the | ||
367 | function with name `foo` in a ModuleId(92) module". Such locations are stable: | ||
368 | adding a new function to the module (unless it is also named `foo`) does not | ||
369 | change the location. However, such "id" ceases to be a `Copy` integer and in | ||
370 | general can become pretty large if we account for nesting (third parameter of | ||
371 | the foo function of the bar impl in the baz module). | ||
372 | |||
373 | [`LocationInterner`] allows us to combine benefits of positional and numeric | ||
374 | ids. It is a bidirectional append only map between locations and consecutive | ||
375 | integers which can "intern" a location and return an integer id back. Salsa | ||
376 | database we use includes a couple of [interners]. How to "garbage collect" | ||
377 | unused locations is an open question. | ||
378 | |||
379 | [`LocationInterner`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_db/src/loc2id.rs#L65-L71 | ||
380 | [interners]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/db.rs#L22-L23 | ||
381 | |||
382 | For example, we use `LocationInterner` to assign ids to defs: functions, | ||
383 | structs, enums, etc. | ||
384 | |||
359 | ## Macros and recursive locations | 385 | ## Macros and recursive locations |
360 | 386 | ||
361 | ## Name resolution | 387 | ## Name resolution |