Skip to main content

resolve_lang/
index.rs

1//! The persistent definition/reference index: the data an LSP needs for
2//! go-to-definition, find-references, rename, and document symbols.
3//!
4//! Built once per resolution and owned by the [`Resolution`](crate::Resolution).
5//! Every lookup is by dense id: definitions and references are vectors, the
6//! references of a definition are one contiguous slice (CSR layout), and
7//! per-unit side tables are keyed by HIR item, variant, binder, and path ids.
8
9use alloc::vec::Vec;
10
11use hir_lang::{
12    BinderId, BinderKind, Def, DefId, ExpnId, Hir, IdKind, ItemId, ItemKind, Name, NodeRef, Origin,
13    PathId, Span, Symbol, UnitId, VariantId,
14};
15
16use crate::model::{NONE, ix};
17
18/// What kind of thing a definition is, for symbol lists and icons.
19///
20/// # Examples
21///
22/// ```
23/// use resolve_lang::SymbolKind;
24///
25/// assert_eq!(SymbolKind::Function.name(), "function");
26/// ```
27#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
28#[non_exhaustive]
29pub enum SymbolKind {
30    /// A module.
31    Module,
32    /// A function or method.
33    Function,
34    /// A record.
35    Record,
36    /// A sum.
37    Sum,
38    /// A sum variant.
39    Variant,
40    /// A class.
41    Class,
42    /// A mixin (PHP trait).
43    Mixin,
44    /// An interface.
45    Interface,
46    /// An impl block.
47    Impl,
48    /// A type alias.
49    Alias,
50    /// An associated type.
51    AssocType,
52    /// A constant.
53    Const,
54    /// A global.
55    Global,
56    /// An aliased import (`use x as y`): `y` is renameable on its own.
57    Import,
58    /// A local variable.
59    Local,
60    /// A parameter.
61    Param,
62    /// An explicit capture or a closure's self binder.
63    Capture,
64    /// A type parameter.
65    TypeParam,
66    /// A const parameter.
67    ConstParam,
68    /// A region parameter.
69    Region,
70    /// A loop or block label.
71    Label,
72    /// A place alias bound by `let_place` (an alias for a place whose
73    /// operands were evaluated once, usually introduced by a template).
74    Place,
75    /// Something outside the program (another package, a host symbol): it
76    /// has references but no location.
77    External,
78}
79
80impl SymbolKind {
81    /// A short lowercase name.
82    ///
83    /// # Examples
84    ///
85    /// ```
86    /// use resolve_lang::SymbolKind;
87    ///
88    /// assert_eq!(SymbolKind::TypeParam.name(), "type parameter");
89    /// ```
90    #[must_use]
91    pub const fn name(self) -> &'static str {
92        match self {
93            Self::Module => "module",
94            Self::Function => "function",
95            Self::Record => "record",
96            Self::Sum => "sum",
97            Self::Variant => "variant",
98            Self::Class => "class",
99            Self::Mixin => "mixin",
100            Self::Interface => "interface",
101            Self::Impl => "impl",
102            Self::Alias => "alias",
103            Self::AssocType => "associated type",
104            Self::Const => "constant",
105            Self::Global => "global",
106            Self::Import => "import",
107            Self::Local => "local",
108            Self::Param => "parameter",
109            Self::Capture => "capture",
110            Self::TypeParam => "type parameter",
111            Self::ConstParam => "const parameter",
112            Self::Region => "region",
113            Self::Label => "label",
114            Self::Place => "place alias",
115            Self::External => "external",
116        }
117    }
118
119    const fn of_item(kind: &ItemKind) -> Self {
120        match kind {
121            ItemKind::Fn(_) => Self::Function,
122            ItemKind::Record(_) => Self::Record,
123            ItemKind::Sum(_) => Self::Sum,
124            ItemKind::Class(c) if c.mixin => Self::Mixin,
125            ItemKind::Class(_) => Self::Class,
126            ItemKind::Interface(_) => Self::Interface,
127            ItemKind::Impl(_) => Self::Impl,
128            ItemKind::Alias { .. } => Self::Alias,
129            ItemKind::AssocType { .. } => Self::AssocType,
130            ItemKind::Const { .. } => Self::Const,
131            ItemKind::Global { .. } => Self::Global,
132            ItemKind::Module { .. } | ItemKind::Err => Self::Module,
133            ItemKind::Import { .. } | ItemKind::MixinUse(_) => Self::Import,
134        }
135    }
136
137    const fn of_binder(kind: BinderKind) -> Self {
138        match kind {
139            BinderKind::Local => Self::Local,
140            BinderKind::Param => Self::Param,
141            BinderKind::Capture => Self::Capture,
142            BinderKind::TypeParam => Self::TypeParam,
143            BinderKind::ConstParam => Self::ConstParam,
144            BinderKind::Region => Self::Region,
145            BinderKind::Label => Self::Label,
146            BinderKind::Place => Self::Place,
147        }
148    }
149}
150
151/// What a definition is, as an identity that survives across units.
152///
153/// # Examples
154///
155/// ```
156/// use hir_lang::{BinderId, UnitId};
157/// use resolve_lang::Target;
158///
159/// let t = Target::Local(UnitId::new(0), BinderId::from_index(3).unwrap());
160/// assert!(matches!(t, Target::Local(..)));
161/// ```
162#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
163pub enum Target {
164    /// An item or variant.
165    Def(DefId),
166    /// A binder of a unit.
167    Local(UnitId, BinderId),
168    /// A host symbol.
169    Extern(Symbol),
170    /// An aliased import item (its own name is the definition).
171    Import(UnitId, ItemId),
172}
173
174/// A place in the source.
175///
176/// # Examples
177///
178/// ```
179/// use hir_lang::{Span, UnitId};
180/// use resolve_lang::Location;
181///
182/// let l = Location { unit: UnitId::new(1), span: Span::new(4, 7), in_source: true };
183/// assert_eq!(l.span.len(), 3);
184/// ```
185#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
186pub struct Location {
187    /// The unit.
188    pub unit: UnitId,
189    /// The span. For a name that came out of a macro or template expansion,
190    /// this is the outermost expansion's call site.
191    pub span: Span,
192    /// Whether the name was written in the source (its origin is not an
193    /// expansion). Only such names are rename edits.
194    pub in_source: bool,
195}
196
197/// An opaque handle to a definition in an [`Index`].
198///
199/// # Examples
200///
201/// ```
202/// use resolve_lang::DefRef;
203///
204/// assert_eq!(DefRef::from_index(5).index(), 5);
205/// ```
206#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
207pub struct DefRef(u32);
208
209impl DefRef {
210    /// The dense position of the definition.
211    ///
212    /// # Examples
213    ///
214    /// ```
215    /// use resolve_lang::DefRef;
216    ///
217    /// assert_eq!(DefRef::from_index(0).index(), 0);
218    /// ```
219    #[must_use]
220    pub const fn index(self) -> usize {
221        self.0 as usize
222    }
223
224    /// A handle from a dense position (saturating past `u32::MAX`).
225    ///
226    /// # Examples
227    ///
228    /// ```
229    /// use resolve_lang::DefRef;
230    ///
231    /// assert_eq!(DefRef::from_index(9), DefRef::from_index(9));
232    /// ```
233    #[must_use]
234    pub const fn from_index(i: usize) -> Self {
235        Self(if i > u32::MAX as usize {
236            u32::MAX
237        } else {
238            i as u32
239        })
240    }
241}
242
243/// One definition.
244///
245/// # Examples
246///
247/// ```
248/// use hir_lang::{Builder, Name};
249/// use intern_lang::Interner;
250/// use resolve_lang::SymbolKind;
251///
252/// let mut names = Interner::new();
253/// let mut b = Builder::new();
254/// let body = b.block(&[], None);
255/// let f = b.func(Name::new(names.intern("f")), &[], body);
256/// let root = b.module(None, &[f]);
257/// let res = resolve_lang::resolve(b.finish(root)?, &names)?;
258/// let def = res.index().definitions().iter().find(|d| d.kind == SymbolKind::Function).unwrap();
259/// assert_eq!(names.resolve(def.name.sym), Some("f"));
260/// # Ok::<(), Box<dyn std::error::Error>>(())
261/// ```
262#[derive(Clone, Copy, Debug, PartialEq, Eq)]
263pub struct Definition {
264    /// What it is.
265    pub target: Target,
266    /// Its name.
267    pub name: Name,
268    /// Its kind.
269    pub kind: SymbolKind,
270    /// Where its name is: `None` for something outside the program, and for
271    /// an item whose lowering recorded no name span (use `range` then).
272    pub location: Option<Location>,
273    /// The span of the whole definition (an item's or binder's own span).
274    pub range: Option<Location>,
275    /// The enclosing item's definition, for symbol trees.
276    pub parent: Option<DefRef>,
277}
278
279/// One resolved name in a path.
280///
281/// # Examples
282///
283/// ```
284/// use resolve_lang::Reference;
285///
286/// fn first_segment(r: &Reference) -> bool { r.segment == 0 }
287/// # let _ = first_segment;
288/// ```
289#[derive(Clone, Copy, Debug, PartialEq, Eq)]
290pub struct Reference {
291    /// Where the name is.
292    pub location: Location,
293    /// What it resolves to.
294    pub def: DefRef,
295    /// The path holding it.
296    pub path: PathId,
297    /// The segment of the path.
298    pub segment: u32,
299    /// The name as written (differs from the definition's name when reached
300    /// through an aliased import).
301    pub name: Name,
302    /// The aliased import the name was reached through, if any.
303    pub via: Option<DefRef>,
304}
305
306/// What [`Index::at`] found at a position.
307///
308/// # Examples
309///
310/// ```
311/// use resolve_lang::{DefRef, Occurrence};
312///
313/// let o = Occurrence { def: DefRef::from_index(0), reference: None };
314/// assert!(o.is_definition());
315/// ```
316#[derive(Clone, Copy, Debug, PartialEq, Eq)]
317pub struct Occurrence {
318    /// The definition named there.
319    pub def: DefRef,
320    /// The reference there (by position in [`Index::references_all`]), or
321    /// `None` if the position is the definition's own name.
322    pub reference: Option<u32>,
323}
324
325impl Occurrence {
326    /// Whether the position is the definition's own name.
327    ///
328    /// # Examples
329    ///
330    /// ```
331    /// use resolve_lang::{DefRef, Occurrence};
332    ///
333    /// let o = Occurrence { def: DefRef::from_index(0), reference: Some(3) };
334    /// assert!(!o.is_definition());
335    /// ```
336    #[must_use]
337    pub const fn is_definition(&self) -> bool {
338        self.reference.is_none()
339    }
340}
341
342/// The references to one definition, in location order: see
343/// [`Index::references`].
344///
345/// # Examples
346///
347/// ```
348/// use resolve_lang::{DefRef, Index};
349///
350/// let index = Index::default();
351/// let mut refs = index.references(DefRef::from_index(3));
352/// assert!(refs.next().is_none());
353/// ```
354#[derive(Clone, Debug)]
355pub struct References<'a> {
356    refs: &'a [Reference],
357    ids: core::slice::Iter<'a, u32>,
358}
359
360impl<'a> Iterator for References<'a> {
361    type Item = &'a Reference;
362
363    fn next(&mut self) -> Option<&'a Reference> {
364        // Every id is a valid position by construction (the CSR is built
365        // from `refs` itself); `get` keeps a corrupted index from panicking.
366        self.ids.find_map(|i| self.refs.get(*i as usize))
367    }
368
369    fn size_hint(&self) -> (usize, Option<usize>) {
370        (self.ids.len(), Some(self.ids.len()))
371    }
372}
373
374impl ExactSizeIterator for References<'_> {}
375
376/// The edits a rename of one definition makes.
377///
378/// # Examples
379///
380/// ```
381/// use resolve_lang::RenameSet;
382///
383/// let r = RenameSet::default();
384/// assert!(r.edits.is_empty() && r.outside_source.is_empty());
385/// ```
386#[derive(Clone, Debug, Default, PartialEq, Eq)]
387pub struct RenameSet {
388    /// Every occurrence written in the source, the definition's name
389    /// included, sorted by location.
390    pub edits: Vec<Location>,
391    /// Occurrences produced by expansions: a rename cannot edit them
392    /// directly (the macro or template that produced them needs a look).
393    pub outside_source: Vec<Location>,
394}
395
396/// Per-unit side tables.
397#[derive(Clone, Debug, Default)]
398struct UnitIx {
399    id: UnitId,
400    item_def: Vec<u32>,
401    variant_def: Vec<u32>,
402    binder_def: Vec<u32>,
403    /// CSR over paths: references of path `p` are `refs[path_off[p]..path_off[p+1]]`.
404    path_off: Vec<u32>,
405    /// Item definitions in preorder.
406    symbols: Vec<u32>,
407    /// (start, end, def, reference or NONE), sorted by (start, end).
408    occ: Vec<(u32, u32, u32, u32)>,
409}
410
411/// The persistent definition/reference index of a resolved program.
412///
413/// # Examples
414///
415/// ```
416/// use hir_lang::{Builder, Name, Span};
417/// use intern_lang::Interner;
418///
419/// // fn f(n) { n }  — the use of `n` is a reference to the parameter.
420/// let mut names = Interner::new();
421/// let n = Name::new(names.intern("n"));
422/// let mut b = Builder::new();
423/// b.set_span(Span::new(5, 6));
424/// let (param, _) = b.local_param(n);
425/// b.set_span(Span::new(10, 11));
426/// let use_n = b.name_expr(n);
427/// let body = b.block(&[], Some(use_n));
428/// let f = b.func(Name::new(names.intern("f")), &[param], body);
429/// let root = b.module(None, &[f]);
430/// let hir = b.finish(root)?;
431/// let unit = hir.unit();
432///
433/// let res = resolve_lang::resolve(hir, &names)?;
434/// let index = res.index();
435/// let hit = index.at(unit, 10).unwrap();
436/// let def = index.definition(hit.def).unwrap();
437/// assert_eq!(def.location.unwrap().span, Span::new(5, 6));
438/// assert_eq!(index.references(hit.def).len(), 1);
439/// # Ok::<(), Box<dyn std::error::Error>>(())
440/// ```
441#[derive(Clone, Debug, Default)]
442pub struct Index {
443    defs: Vec<Definition>,
444    refs: Vec<Reference>,
445    by_def_off: Vec<u32>,
446    by_def: Vec<u32>,
447    /// (aliased-import definition, reference), sorted.
448    by_via: Vec<(u32, u32)>,
449    /// External definitions by target, sorted.
450    externals: Vec<(Target, u32)>,
451    units: Vec<UnitIx>,
452    /// By reference: whether it spells its definition's name (up to the
453    /// case folding of the policy), so a rename edits it.
454    same_name: Vec<bool>,
455}
456
457/// Maps an origin to a source location, through expansions.
458struct Mapper {
459    unit: UnitId,
460    /// By expansion id (1-based): the outermost call site.
461    sites: Vec<Span>,
462}
463
464impl Mapper {
465    fn new(hir: &Hir) -> Self {
466        let n = hir.count(IdKind::Expansion);
467        let mut sites: Vec<Span> = Vec::with_capacity(n);
468        for i in 1..=n {
469            let e = hir.expansion(ExpnId::from_u32(ix(i)));
470            let site = match e {
471                Some(e) if e.parent.is_root() => e.call_site,
472                Some(e) => sites
473                    .get((e.parent.as_u32() as usize).saturating_sub(1))
474                    .copied()
475                    .unwrap_or(e.call_site),
476                None => Span::empty(0),
477            };
478            sites.push(site);
479        }
480        Self {
481            unit: hir.unit(),
482            sites,
483        }
484    }
485
486    fn map(&self, origin: Origin) -> Location {
487        self.span(origin.span, origin.expn)
488    }
489
490    fn span(&self, span: Span, expn: ExpnId) -> Location {
491        if expn.is_root() {
492            return Location {
493                unit: self.unit,
494                span,
495                in_source: true,
496            };
497        }
498        let site = self
499            .sites
500            .get((expn.as_u32() as usize).saturating_sub(1))
501            .copied()
502            .unwrap_or(span);
503        Location {
504            unit: self.unit,
505            span: site,
506            in_source: false,
507        }
508    }
509}
510
511/// A reference waiting to be indexed: (path, segment, target, via import
512/// target).
513pub(crate) struct RawRef {
514    pub(crate) path: PathId,
515    pub(crate) seg: u32,
516    pub(crate) target: Target,
517    pub(crate) via: Option<Target>,
518}
519
520/// The input of one unit to the index build.
521pub(crate) struct UnitInput<'a> {
522    pub(crate) hir: &'a Hir,
523    pub(crate) refs: Vec<RawRef>,
524    /// `Pat::Ident` binders that did not bind (their path named a constant).
525    pub(crate) dead_binders: Vec<BinderId>,
526    /// Aliased import items.
527    pub(crate) aliases: Vec<ItemId>,
528}
529
530impl Index {
531    /// Builds the index of a whole program. `fold` decides which spellings
532    /// of a name are the same name (case-insensitive tables).
533    pub(crate) fn build(units: &[UnitInput<'_>], fold: &crate::model::Fold) -> Self {
534        let mut me = Self::default();
535        let mut maps: Vec<Mapper> = Vec::with_capacity(units.len());
536        for u in units {
537            maps.push(Mapper::new(u.hir));
538            me.units.push(UnitIx {
539                id: u.hir.unit(),
540                item_def: alloc::vec![NONE; u.hir.count(IdKind::Item)],
541                variant_def: alloc::vec![NONE; u.hir.count(IdKind::Variant)],
542                binder_def: alloc::vec![NONE; u.hir.count(IdKind::Binder)],
543                path_off: Vec::new(),
544                symbols: Vec::new(),
545                occ: Vec::new(),
546            });
547        }
548        for (ui, u) in units.iter().enumerate() {
549            let Some(map) = maps.get(ui) else { continue };
550            me.collect_defs(ui, u, map);
551        }
552        // External definitions are created on first reference; keep them
553        // findable by target.
554        let mut externals: Vec<(Target, u32)> = Vec::new();
555        let mut by_via: Vec<(u32, u32)> = Vec::new();
556        for (ui, u) in units.iter().enumerate() {
557            let Some(map) = maps.get(ui) else { continue };
558            let mut refs: Vec<&RawRef> = u.refs.iter().collect();
559            refs.sort_by_key(|r| (r.path, r.seg));
560            refs.dedup_by_key(|r| (r.path, r.seg));
561            let n_paths = u.hir.count(IdKind::Path);
562            let mut off: Vec<u32> = alloc::vec![0; n_paths + 1];
563            for r in refs {
564                let path = u.hir.path(r.path);
565                let Some(seg) = u.hir.list(path.segments).get(r.seg as usize) else {
566                    continue;
567                };
568                let Some(def) = me.target_def(r.target, seg.name, &mut externals) else {
569                    continue;
570                };
571                let via = r.via.and_then(|t| me.find_target(t, &externals));
572                if let Some(v) = via {
573                    by_via.push((v.0, ix(me.refs.len())));
574                }
575                let same = me.defs.get(def as usize).is_some_and(|d| {
576                    d.name == seg.name
577                        || (via.is_none() && fold.name(d.name) == fold.name(seg.name))
578                });
579                me.same_name.push(same);
580                let reference = Reference {
581                    location: map.map(seg.origin),
582                    def: DefRef(def),
583                    path: r.path,
584                    segment: r.seg,
585                    name: seg.name,
586                    via,
587                };
588                if let Some(o) = off.get_mut(r.path.index() + 1) {
589                    *o += 1;
590                }
591                me.refs.push(reference);
592            }
593            // Prefix sums turn counts into offsets relative to this unit's
594            // first reference.
595            let base = ix(me.refs.len()) - off.iter().sum::<u32>();
596            let mut acc = base;
597            for o in &mut off {
598                acc += *o;
599                *o = acc;
600            }
601            if let Some(slot) = me.units.get_mut(ui) {
602                slot.path_off = off;
603            }
604        }
605        by_via.sort_unstable();
606        me.by_via = by_via;
607        me.externals = externals;
608        me.build_by_def();
609        me.build_occurrences();
610        me
611    }
612
613    fn push_def(&mut self, d: Definition) -> u32 {
614        let i = ix(self.defs.len());
615        self.defs.push(d);
616        i
617    }
618
619    fn collect_defs(&mut self, ui: usize, u: &UnitInput<'_>, map: &Mapper) {
620        let hir = u.hir;
621        let unit = hir.unit();
622        let mut stack: Vec<u32> = Vec::new();
623        let mut dead = u.dead_binders.clone();
624        dead.sort();
625        let mut symbols: Vec<u32> = Vec::new();
626        let mut items: Vec<(ItemId, u32)> = Vec::new();
627        let mut variants: Vec<(VariantId, u32)> = Vec::new();
628        let mut binders: Vec<(BinderId, u32)> = Vec::new();
629        let root = hir.root();
630        let mut defs_out: Vec<Definition> = Vec::new();
631        let base = ix(self.defs.len());
632        hir.walk_from(NodeRef::Item(root), |ev| {
633            match ev {
634                hir_lang::Event::Enter(NodeRef::Item(i)) => {
635                    let item = hir.item(i);
636                    let alias = u.aliases.binary_search(&i).is_ok();
637                    let named = item.name.filter(|_| {
638                        !matches!(item.kind, ItemKind::Import { .. } | ItemKind::MixinUse(_))
639                            || alias
640                    });
641                    match named {
642                        Some(name) if i != root || item.name.is_some() => {
643                            let target = if alias {
644                                Target::Import(unit, i)
645                            } else {
646                                Target::Def(DefId::foreign(unit, Def::Item(i)))
647                            };
648                            let d = base + ix(defs_out.len());
649                            defs_out.push(Definition {
650                                target,
651                                name,
652                                kind: if alias {
653                                    SymbolKind::Import
654                                } else {
655                                    SymbolKind::of_item(&item.kind)
656                                },
657                                // Lowering that leaves the name span unset
658                                // gives no name location (the range still
659                                // locates the item).
660                                location: (item.name_span != Span::empty(0)).then(|| {
661                                    map.span(item.name_span, hir.origin(NodeRef::Item(i)).expn)
662                                }),
663                                range: Some(map.map(hir.origin(NodeRef::Item(i)))),
664                                parent: stack.last().copied().filter(|p| *p != NONE).map(DefRef),
665                            });
666                            items.push((i, d));
667                            symbols.push(d);
668                            stack.push(d);
669                            if let ItemKind::Sum(sum) = item.kind {
670                                for &v in hir.list(sum.variants) {
671                                    let Some(var) = hir.variant(v) else { continue };
672                                    let vd = base + ix(defs_out.len());
673                                    let origin = hir.origin(NodeRef::Variant(v));
674                                    defs_out.push(Definition {
675                                        target: Target::Def(DefId::foreign(unit, Def::Variant(v))),
676                                        name: Name::new(var.name.sym),
677                                        kind: SymbolKind::Variant,
678                                        location: Some(map.span(var.name.span, origin.expn)),
679                                        range: Some(map.map(origin)),
680                                        parent: Some(DefRef(d)),
681                                    });
682                                    variants.push((v, vd));
683                                    symbols.push(vd);
684                                }
685                            }
686                        }
687                        _ => stack.push(NONE),
688                    }
689                }
690                hir_lang::Event::Leave(NodeRef::Item(_)) => {
691                    let _ = stack.pop();
692                }
693                hir_lang::Event::Bind(b) => {
694                    if dead.binary_search(&b).is_ok() {
695                        return hir_lang::Control::Continue;
696                    }
697                    let Some(binder) = hir.binder(b) else {
698                        return hir_lang::Control::Continue;
699                    };
700                    let origin = hir.binder_origin(b);
701                    let d = base + ix(defs_out.len());
702                    defs_out.push(Definition {
703                        target: Target::Local(unit, b),
704                        name: binder.name,
705                        kind: SymbolKind::of_binder(binder.kind),
706                        location: Some(map.map(origin)),
707                        range: Some(map.map(origin)),
708                        parent: stack.iter().rev().copied().find(|p| *p != NONE).map(DefRef),
709                    });
710                    binders.push((b, d));
711                }
712                _ => {}
713            }
714            hir_lang::Control::Continue
715        });
716        self.defs.extend(defs_out);
717        if let Some(slot) = self.units.get_mut(ui) {
718            for (i, d) in items {
719                if let Some(x) = slot.item_def.get_mut(i.index()) {
720                    *x = d;
721                }
722            }
723            for (v, d) in variants {
724                if let Some(x) = slot.variant_def.get_mut(v.index()) {
725                    *x = d;
726                }
727            }
728            for (b, d) in binders {
729                if let Some(x) = slot.binder_def.get_mut(b.index()) {
730                    *x = d;
731                }
732            }
733            slot.symbols = symbols;
734        }
735    }
736
737    fn unit_ix(&self, unit: UnitId) -> Option<&UnitIx> {
738        self.units.iter().find(|u| u.id == unit)
739    }
740
741    fn find_target(&self, t: Target, externals: &[(Target, u32)]) -> Option<DefRef> {
742        let local = match t {
743            Target::Def(d) => self.unit_ix(d.unit()).and_then(|u| match d.def() {
744                Def::Item(i) => u.item_def.get(i.index()).copied(),
745                Def::Variant(v) => u.variant_def.get(v.index()).copied(),
746            }),
747            Target::Local(unit, b) => self
748                .unit_ix(unit)
749                .and_then(|u| u.binder_def.get(b.index()).copied()),
750            Target::Import(unit, i) => self
751                .unit_ix(unit)
752                .and_then(|u| u.item_def.get(i.index()).copied()),
753            Target::Extern(_) => None,
754        };
755        match local.filter(|d| *d != NONE) {
756            Some(d) => Some(DefRef(d)),
757            None => externals
758                .binary_search_by(|(x, _)| x.cmp(&t))
759                .ok()
760                .and_then(|i| externals.get(i))
761                .map(|(_, d)| DefRef(*d)),
762        }
763    }
764
765    /// The definition of a target, creating an external one (named as the
766    /// reference spells it) if needed.
767    fn target_def(
768        &mut self,
769        t: Target,
770        spelled: Name,
771        externals: &mut Vec<(Target, u32)>,
772    ) -> Option<u32> {
773        if let Some(d) = self.find_target(t, externals) {
774            return Some(d.0);
775        }
776        let name = match t {
777            // A program target with no definition entry (an unnamed item):
778            // nothing to point at.
779            Target::Def(d) if self.unit_ix(d.unit()).is_some() => return None,
780            Target::Local(..) | Target::Import(..) => return None,
781            Target::Extern(s) => Name::new(s),
782            Target::Def(_) => spelled,
783        };
784        let d = self.push_def(Definition {
785            target: t,
786            name,
787            kind: SymbolKind::External,
788            location: None,
789            range: None,
790            parent: None,
791        });
792        let at = externals.partition_point(|(x, _)| *x < t);
793        externals.insert(at, (t, d));
794        Some(d)
795    }
796
797    fn build_by_def(&mut self) {
798        let n = self.defs.len();
799        let mut count: Vec<u32> = alloc::vec![0; n + 1];
800        for r in &self.refs {
801            if let Some(c) = count.get_mut(r.def.index() + 1) {
802                *c += 1;
803            }
804        }
805        for i in 1..count.len() {
806            let prev = count.get(i - 1).copied().unwrap_or(0);
807            if let Some(c) = count.get_mut(i) {
808                *c += prev;
809            }
810        }
811        let mut fill = count.clone();
812        let mut by_def: Vec<u32> = alloc::vec![0; self.refs.len()];
813        // References are visited in location order so each slice is sorted.
814        let mut order: Vec<u32> = (0..ix(self.refs.len())).collect();
815        order.sort_by_key(|i| self.refs.get(*i as usize).map(|r| r.location));
816        for i in order {
817            let Some(r) = self.refs.get(i as usize) else {
818                continue;
819            };
820            if let Some(f) = fill.get_mut(r.def.index()) {
821                if let Some(slot) = by_def.get_mut(*f as usize) {
822                    *slot = i;
823                }
824                *f += 1;
825            }
826        }
827        self.by_def_off = count;
828        self.by_def = by_def;
829    }
830
831    fn build_occurrences(&mut self) {
832        let mut per_unit: Vec<Vec<(u32, u32, u32, u32)>> =
833            self.units.iter().map(|_| Vec::new()).collect();
834        let unit_pos = |units: &[UnitIx], id: UnitId| units.iter().position(|u| u.id == id);
835        for (d, def) in self.defs.iter().enumerate() {
836            let Some(loc) = def.location.filter(|l| l.in_source && !l.span.is_empty()) else {
837                continue;
838            };
839            if let Some(list) = unit_pos(&self.units, loc.unit).and_then(|u| per_unit.get_mut(u)) {
840                list.push((
841                    loc.span.start().to_u32(),
842                    loc.span.end().to_u32(),
843                    ix(d),
844                    NONE,
845                ));
846            }
847        }
848        for (i, r) in self.refs.iter().enumerate() {
849            let loc = r.location;
850            if !loc.in_source || loc.span.is_empty() {
851                continue;
852            }
853            if let Some(list) = unit_pos(&self.units, loc.unit).and_then(|u| per_unit.get_mut(u)) {
854                list.push((
855                    loc.span.start().to_u32(),
856                    loc.span.end().to_u32(),
857                    r.def.0,
858                    ix(i),
859                ));
860            }
861        }
862        for (u, mut list) in self.units.iter_mut().zip(per_unit) {
863            list.sort_unstable();
864            list.dedup_by_key(|x| (x.0, x.1));
865            u.occ = list;
866        }
867    }
868
869    // ----------------------------------------------------------------- API
870
871    /// Every definition, in unit order, then preorder (externals last).
872    ///
873    /// # Examples
874    ///
875    /// ```
876    /// use resolve_lang::Index;
877    ///
878    /// assert!(Index::default().definitions().is_empty());
879    /// ```
880    #[must_use]
881    pub fn definitions(&self) -> &[Definition] {
882        &self.defs
883    }
884
885    /// Every reference, by unit, then path, then segment.
886    ///
887    /// # Examples
888    ///
889    /// ```
890    /// use resolve_lang::Index;
891    ///
892    /// assert!(Index::default().references_all().is_empty());
893    /// ```
894    #[must_use]
895    pub fn references_all(&self) -> &[Reference] {
896        &self.refs
897    }
898
899    /// One definition.
900    ///
901    /// # Examples
902    ///
903    /// ```
904    /// use resolve_lang::{DefRef, Index};
905    ///
906    /// assert!(Index::default().definition(DefRef::from_index(0)).is_none());
907    /// ```
908    #[must_use]
909    pub fn definition(&self, def: DefRef) -> Option<&Definition> {
910        self.defs.get(def.index())
911    }
912
913    /// The references to a definition, sorted by location (find-references).
914    /// Allocation-free: an iterator over the definition's slice.
915    ///
916    /// # Examples
917    ///
918    /// ```
919    /// use resolve_lang::{DefRef, Index};
920    ///
921    /// assert_eq!(Index::default().references(DefRef::from_index(0)).len(), 0);
922    /// ```
923    #[must_use]
924    pub fn references(&self, def: DefRef) -> References<'_> {
925        let ids = match (
926            self.by_def_off.get(def.index()),
927            self.by_def_off.get(def.index() + 1),
928        ) {
929            (Some(&lo), Some(&hi)) => self.by_def.get(lo as usize..hi as usize).unwrap_or(&[]),
930            _ => &[],
931        };
932        References {
933            refs: &self.refs,
934            ids: ids.iter(),
935        }
936    }
937
938    /// The definition of a target (an item, variant, binder, aliased import,
939    /// or a referenced external symbol).
940    ///
941    /// # Examples
942    ///
943    /// ```
944    /// use hir_lang::{BinderId, UnitId};
945    /// use resolve_lang::{Index, Target};
946    ///
947    /// let t = Target::Local(UnitId::new(0), BinderId::from_index(0).unwrap());
948    /// assert!(Index::default().def_of(t).is_none());
949    /// ```
950    #[must_use]
951    pub fn def_of(&self, target: Target) -> Option<DefRef> {
952        self.find_target(target, &self.externals)
953    }
954
955    /// Go-to-definition by HIR id: what segment `segment` of `path` names.
956    ///
957    /// # Examples
958    ///
959    /// ```
960    /// use hir_lang::{PathId, UnitId};
961    /// use resolve_lang::Index;
962    ///
963    /// assert!(Index::default().resolve_at(UnitId::new(0), PathId::from_index(0).unwrap(), 0).is_none());
964    /// ```
965    #[must_use]
966    pub fn resolve_at(&self, unit: UnitId, path: PathId, segment: u32) -> Option<DefRef> {
967        let u = self.unit_ix(unit)?;
968        let lo = *u.path_off.get(path.index())? as usize;
969        let hi = *u.path_off.get(path.index() + 1)? as usize;
970        self.refs
971            .get(lo..hi)?
972            .iter()
973            .find(|r| r.segment == segment)
974            .map(|r| r.def)
975    }
976
977    /// The references inside one path, by segment.
978    ///
979    /// # Examples
980    ///
981    /// ```
982    /// use hir_lang::{PathId, UnitId};
983    /// use resolve_lang::Index;
984    ///
985    /// assert!(Index::default().path_references(UnitId::new(0), PathId::from_index(0).unwrap()).is_empty());
986    /// ```
987    #[must_use]
988    pub fn path_references(&self, unit: UnitId, path: PathId) -> &[Reference] {
989        let Some(u) = self.unit_ix(unit) else {
990            return &[];
991        };
992        let (Some(&lo), Some(&hi)) = (
993            u.path_off.get(path.index()),
994            u.path_off.get(path.index() + 1),
995        ) else {
996            return &[];
997        };
998        self.refs.get(lo as usize..hi as usize).unwrap_or(&[])
999    }
1000
1001    /// Go-to-definition by position: the definition or reference whose name
1002    /// contains byte `offset` of `unit`'s source.
1003    ///
1004    /// # Examples
1005    ///
1006    /// ```
1007    /// use hir_lang::UnitId;
1008    /// use resolve_lang::Index;
1009    ///
1010    /// assert!(Index::default().at(UnitId::new(0), 3).is_none());
1011    /// ```
1012    #[must_use]
1013    pub fn at(&self, unit: UnitId, offset: u32) -> Option<Occurrence> {
1014        let u = self.unit_ix(unit)?;
1015        let upper = u.occ.partition_point(|(s, _, _, _)| *s <= offset);
1016        // Names do not overlap in practice; look back a few entries for
1017        // the innermost one that contains the offset.
1018        let lo = upper.saturating_sub(8);
1019        u.occ
1020            .get(lo..upper)?
1021            .iter()
1022            .rev()
1023            .find(|(s, e, _, _)| *s <= offset && offset < *e)
1024            .map(|&(_, _, d, r)| Occurrence {
1025                def: DefRef(d),
1026                reference: (r != NONE).then_some(r),
1027            })
1028    }
1029
1030    /// Every edit renaming a definition implies: its own name and every
1031    /// reference that spells the same name, up to the case folding of a
1032    /// case-insensitive table (references through an aliased
1033    /// import spell the alias and are left alone). Renaming an aliased
1034    /// import edits the alias and the references that went through it.
1035    ///
1036    /// # Examples
1037    ///
1038    /// ```
1039    /// use resolve_lang::{DefRef, Index};
1040    ///
1041    /// assert!(Index::default().rename_set(DefRef::from_index(0)).edits.is_empty());
1042    /// ```
1043    #[must_use]
1044    pub fn rename_set(&self, def: DefRef) -> RenameSet {
1045        let mut set = RenameSet::default();
1046        let Some(d) = self.definition(def) else {
1047            return set;
1048        };
1049        let mut add = |loc: Location| {
1050            if loc.in_source {
1051                set.edits.push(loc);
1052            } else {
1053                set.outside_source.push(loc);
1054            }
1055        };
1056        if let Some(loc) = d.location {
1057            add(loc);
1058        }
1059        if let Target::Import(..) = d.target {
1060            // The alias's references point at the import's target; take the
1061            // ones that went through this import.
1062            let lo = self.by_via.partition_point(|(v, _)| *v < def.0);
1063            for &(v, r) in self.by_via.get(lo..).unwrap_or(&[]) {
1064                if v != def.0 {
1065                    break;
1066                }
1067                if let Some(r) = self.refs.get(r as usize).filter(|r| r.name == d.name) {
1068                    add(r.location);
1069                }
1070            }
1071        } else {
1072            let ids = match (
1073                self.by_def_off.get(def.index()),
1074                self.by_def_off.get(def.index() + 1),
1075            ) {
1076                (Some(&lo), Some(&hi)) => self.by_def.get(lo as usize..hi as usize).unwrap_or(&[]),
1077                _ => &[],
1078            };
1079            for &r in ids {
1080                let same = self.same_name.get(r as usize).copied().unwrap_or(false);
1081                if let Some(r) = self.refs.get(r as usize).filter(|_| same) {
1082                    add(r.location);
1083                }
1084            }
1085        }
1086        set.edits.sort();
1087        set.edits.dedup();
1088        set.outside_source.sort();
1089        set.outside_source.dedup();
1090        set
1091    }
1092
1093    /// The item definitions of a unit in preorder (with `parent` links), for
1094    /// a document outline.
1095    ///
1096    /// # Examples
1097    ///
1098    /// ```
1099    /// use hir_lang::UnitId;
1100    /// use resolve_lang::Index;
1101    ///
1102    /// assert!(Index::default().document_symbols(UnitId::new(0)).is_empty());
1103    /// ```
1104    #[must_use]
1105    pub fn document_symbols(&self, unit: UnitId) -> Vec<(DefRef, &Definition)> {
1106        let Some(u) = self.unit_ix(unit) else {
1107            return Vec::new();
1108        };
1109        u.symbols
1110            .iter()
1111            .filter_map(|d| self.defs.get(*d as usize).map(|def| (DefRef(*d), def)))
1112            .collect()
1113    }
1114}
1115
1116#[cfg(test)]
1117#[allow(clippy::unwrap_used, clippy::expect_used)]
1118mod tests {
1119    use hir_lang::{Builder, Expansion, ExpnKind, Name, Symbol};
1120
1121    use super::*;
1122
1123    #[test]
1124    fn test_mapper_maps_nested_expansions_to_outermost_call_site() {
1125        let mut b = Builder::new();
1126        let sym = Symbol::from_u32(1).unwrap();
1127        let outer = b.expansion(Expansion {
1128            kind: ExpnKind::Macro,
1129            name: sym,
1130            call_site: Span::new(100, 110),
1131            parent: ExpnId::ROOT,
1132            def_site: ExpnId::ROOT,
1133        });
1134        let inner = b.expansion(Expansion {
1135            kind: ExpnKind::Template,
1136            name: sym,
1137            call_site: Span::new(5, 6),
1138            parent: outer,
1139            def_site: ExpnId::ROOT,
1140        });
1141        let root = b.module(None, &[]);
1142        let hir = b.finish(root).unwrap();
1143        let map = Mapper::new(&hir);
1144        let loc = map.span(Span::new(1, 2), inner);
1145        assert_eq!(loc.span, Span::new(100, 110));
1146        assert!(!loc.in_source);
1147        let loc = map.span(Span::new(1, 2), ExpnId::ROOT);
1148        assert_eq!(loc.span, Span::new(1, 2));
1149        assert!(loc.in_source);
1150    }
1151
1152    #[test]
1153    fn test_empty_index_answers_nothing() {
1154        let ix = Index::default();
1155        let d = DefRef::from_index(0);
1156        assert!(ix.definition(d).is_none());
1157        assert_eq!(ix.references(d).len(), 0);
1158        assert!(ix.rename_set(d).edits.is_empty());
1159        assert!(ix.at(UnitId::new(0), 0).is_none());
1160        let t = Target::Extern(Symbol::from_u32(1).unwrap());
1161        assert!(ix.def_of(t).is_none());
1162        let _ = Name::new(Symbol::from_u32(1).unwrap());
1163    }
1164
1165    #[test]
1166    fn test_def_ref_saturates() {
1167        assert_eq!(DefRef::from_index(usize::MAX).index(), u32::MAX as usize);
1168    }
1169}