hir_def/
find_path.rs

1//! An algorithm to find a path to refer to a certain item.
2
3use std::{cell::Cell, cmp::Ordering, iter};
4
5use base_db::{Crate, CrateOrigin, LangCrateOrigin};
6use hir_expand::{
7    Lookup,
8    mod_path::{ModPath, PathKind},
9    name::{AsName, Name},
10};
11use intern::sym;
12use rustc_hash::FxHashSet;
13
14use crate::{
15    ImportPathConfig, ModuleDefId, ModuleId,
16    db::DefDatabase,
17    item_scope::ItemInNs,
18    nameres::DefMap,
19    visibility::{Visibility, VisibilityExplicitness},
20};
21
22/// Find a path that can be used to refer to a certain item. This can depend on
23/// *from where* you're referring to the item, hence the `from` parameter.
24pub fn find_path(
25    db: &dyn DefDatabase,
26    item: ItemInNs,
27    from: ModuleId,
28    mut prefix_kind: PrefixKind,
29    ignore_local_imports: bool,
30    mut cfg: ImportPathConfig,
31) -> Option<ModPath> {
32    let _p = tracing::info_span!("find_path").entered();
33
34    // - if the item is a builtin, it's in scope
35    if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item {
36        return Some(ModPath::from_segments(PathKind::Plain, iter::once(builtin.as_name())));
37    }
38
39    // within block modules, forcing a `self` or `crate` prefix will not allow using inner items, so
40    // default to plain paths.
41    let item_module = item.module(db)?;
42    if item_module.is_within_block() {
43        prefix_kind = PrefixKind::Plain;
44    }
45    cfg.prefer_no_std = cfg.prefer_no_std || db.crate_supports_no_std(from.krate());
46
47    find_path_inner(
48        &FindPathCtx {
49            db,
50            prefix: prefix_kind,
51            cfg,
52            ignore_local_imports,
53            is_std_item: item_module.krate().data(db).origin.is_lang(),
54            from,
55            from_def_map: from.def_map(db),
56            fuel: Cell::new(FIND_PATH_FUEL),
57        },
58        item,
59        MAX_PATH_LEN,
60    )
61}
62
63#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
64enum Stability {
65    Unstable,
66    Stable,
67}
68use Stability::*;
69
70const MAX_PATH_LEN: usize = 15;
71const FIND_PATH_FUEL: usize = 10000;
72
73#[derive(Copy, Clone, Debug, PartialEq, Eq)]
74pub enum PrefixKind {
75    /// Causes paths to always start with either `self`, `super`, `crate` or a crate-name.
76    /// This is the same as plain, just that paths will start with `self` prepended if the path
77    /// starts with an identifier that is not a crate.
78    BySelf,
79    /// Causes paths to not use a self, super or crate prefix.
80    Plain,
81    /// Causes paths to start with `crate` where applicable, effectively forcing paths to be absolute.
82    ByCrate,
83}
84
85impl PrefixKind {
86    #[inline]
87    fn path_kind(self) -> PathKind {
88        match self {
89            PrefixKind::BySelf => PathKind::SELF,
90            PrefixKind::Plain => PathKind::Plain,
91            PrefixKind::ByCrate => PathKind::Crate,
92        }
93    }
94}
95
96struct FindPathCtx<'db> {
97    db: &'db dyn DefDatabase,
98    prefix: PrefixKind,
99    cfg: ImportPathConfig,
100    ignore_local_imports: bool,
101    is_std_item: bool,
102    from: ModuleId,
103    from_def_map: &'db DefMap,
104    fuel: Cell<usize>,
105}
106
107/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId
108fn find_path_inner(ctx: &FindPathCtx<'_>, item: ItemInNs, max_len: usize) -> Option<ModPath> {
109    // - if the item is a module, jump straight to module search
110    if !ctx.is_std_item
111        && let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item
112    {
113        return find_path_for_module(ctx, &mut FxHashSet::default(), module_id, true, max_len)
114            .map(|choice| choice.path);
115    }
116
117    let may_be_in_scope = match ctx.prefix {
118        PrefixKind::Plain | PrefixKind::BySelf => true,
119        PrefixKind::ByCrate => ctx.from.is_crate_root(),
120    };
121    if may_be_in_scope {
122        // - if the item is already in scope, return the name under which it is
123        let scope_name =
124            find_in_scope(ctx.db, ctx.from_def_map, ctx.from, item, ctx.ignore_local_imports);
125        if let Some(scope_name) = scope_name {
126            return Some(ModPath::from_segments(ctx.prefix.path_kind(), iter::once(scope_name)));
127        }
128    }
129
130    // - if the item is in the prelude, return the name from there
131    if let Some(value) = find_in_prelude(ctx.db, ctx.from_def_map, item, ctx.from) {
132        return Some(value.path);
133    }
134
135    if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() {
136        // - if the item is an enum variant, refer to it via the enum
137        let loc = variant.lookup(ctx.db);
138        if let Some(mut path) = find_path_inner(ctx, ItemInNs::Types(loc.parent.into()), max_len) {
139            path.push_segment(
140                loc.parent.enum_variants(ctx.db).variants[loc.index as usize].1.clone(),
141            );
142            return Some(path);
143        }
144        // If this doesn't work, it seems we have no way of referring to the
145        // enum; that's very weird, but there might still be a reexport of the
146        // variant somewhere
147    }
148
149    let mut best_choice = None;
150    calculate_best_path(ctx, &mut FxHashSet::default(), item, max_len, &mut best_choice);
151    best_choice.map(|choice| choice.path)
152}
153
154#[tracing::instrument(skip_all)]
155fn find_path_for_module(
156    ctx: &FindPathCtx<'_>,
157    visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
158    module_id: ModuleId,
159    maybe_extern: bool,
160    max_len: usize,
161) -> Option<Choice> {
162    if max_len == 0 {
163        // recursive base case, we can't find a path of length 0
164        return None;
165    }
166    if let Some(crate_root) = module_id.as_crate_root() {
167        if !maybe_extern || crate_root == ctx.from.derive_crate_root() {
168            // - if the item is the crate root, return `crate`
169            return Some(Choice {
170                path: ModPath::from_segments(PathKind::Crate, None),
171                path_text_len: 5,
172                stability: Stable,
173                prefer_due_to_prelude: false,
174            });
175        }
176        // - otherwise if the item is the crate root of a dependency crate, return the name from the extern prelude
177
178        let root_local_def_map = ctx.from.derive_crate_root().local_def_map(ctx.db).1;
179        // rev here so we prefer looking at renamed extern decls first
180        for (name, (def_id, _extern_crate)) in root_local_def_map.extern_prelude().rev() {
181            if crate_root != def_id {
182                continue;
183            }
184            let name_already_occupied_in_type_ns = ctx
185                .from_def_map
186                .with_ancestor_maps(ctx.db, ctx.from.local_id, &mut |def_map, local_id| {
187                    def_map[local_id]
188                        .scope
189                        .type_(name)
190                        .filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id.into()))
191                })
192                .is_some();
193            let kind = if name_already_occupied_in_type_ns {
194                cov_mark::hit!(ambiguous_crate_start);
195                PathKind::Abs
196            } else if ctx.cfg.prefer_absolute {
197                PathKind::Abs
198            } else {
199                PathKind::Plain
200            };
201            return Some(Choice::new(ctx.cfg.prefer_prelude, kind, name.clone(), Stable));
202        }
203    }
204
205    let may_be_in_scope = match ctx.prefix {
206        PrefixKind::Plain | PrefixKind::BySelf => true,
207        PrefixKind::ByCrate => ctx.from.is_crate_root(),
208    };
209    if may_be_in_scope {
210        let scope_name = find_in_scope(
211            ctx.db,
212            ctx.from_def_map,
213            ctx.from,
214            ItemInNs::Types(module_id.into()),
215            ctx.ignore_local_imports,
216        );
217        if let Some(scope_name) = scope_name {
218            // - if the item is already in scope, return the name under which it is
219            return Some(Choice::new(
220                ctx.cfg.prefer_prelude,
221                ctx.prefix.path_kind(),
222                scope_name,
223                Stable,
224            ));
225        }
226    }
227
228    // - if the module can be referenced as self, super or crate, do that
229    if let Some(kind) = is_kw_kind_relative_to_from(ctx.from_def_map, module_id, ctx.from)
230        && (ctx.prefix != PrefixKind::ByCrate || kind == PathKind::Crate)
231    {
232        return Some(Choice {
233            path: ModPath::from_segments(kind, None),
234            path_text_len: path_kind_len(kind),
235            stability: Stable,
236            prefer_due_to_prelude: false,
237        });
238    }
239
240    // - if the module is in the prelude, return it by that path
241    let item = ItemInNs::Types(module_id.into());
242    if let Some(choice) = find_in_prelude(ctx.db, ctx.from_def_map, item, ctx.from) {
243        return Some(choice);
244    }
245    let mut best_choice = None;
246    if maybe_extern {
247        calculate_best_path(ctx, visited_modules, item, max_len, &mut best_choice);
248    } else {
249        calculate_best_path_local(ctx, visited_modules, item, max_len, &mut best_choice);
250    }
251    best_choice
252}
253
254fn find_in_scope(
255    db: &dyn DefDatabase,
256    def_map: &DefMap,
257    from: ModuleId,
258    item: ItemInNs,
259    ignore_local_imports: bool,
260) -> Option<Name> {
261    // FIXME: We could have multiple applicable names here, but we currently only return the first
262    def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
263        def_map[local_id].scope.names_of(item, |name, _, declared| {
264            (declared || !ignore_local_imports).then(|| name.clone())
265        })
266    })
267}
268
269/// Returns single-segment path (i.e. without any prefix) if `item` is found in prelude and its
270/// name doesn't clash in current scope.
271fn find_in_prelude(
272    db: &dyn DefDatabase,
273    local_def_map: &DefMap,
274    item: ItemInNs,
275    from: ModuleId,
276) -> Option<Choice> {
277    let (prelude_module, _) = local_def_map.prelude()?;
278    let prelude_def_map = prelude_module.def_map(db);
279    let prelude_scope = &prelude_def_map[prelude_module.local_id].scope;
280    let (name, vis, _declared) = prelude_scope.name_of(item)?;
281    if !vis.is_visible_from(db, from) {
282        return None;
283    }
284
285    // Check if the name is in current scope and it points to the same def.
286    let found_and_same_def =
287        local_def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
288            let per_ns = def_map[local_id].scope.get(name);
289            let same_def = match item {
290                ItemInNs::Types(it) => per_ns.take_types()? == it,
291                ItemInNs::Values(it) => per_ns.take_values()? == it,
292                ItemInNs::Macros(it) => per_ns.take_macros()? == it,
293            };
294            Some(same_def)
295        });
296
297    if found_and_same_def.unwrap_or(true) {
298        Some(Choice::new(false, PathKind::Plain, name.clone(), Stable))
299    } else {
300        None
301    }
302}
303
304fn is_kw_kind_relative_to_from(
305    def_map: &DefMap,
306    item: ModuleId,
307    from: ModuleId,
308) -> Option<PathKind> {
309    if item.krate != from.krate || item.is_within_block() || from.is_within_block() {
310        return None;
311    }
312    let item = item.local_id;
313    let from = from.local_id;
314    if item == from {
315        // - if the item is the module we're in, use `self`
316        Some(PathKind::SELF)
317    } else if let Some(parent_id) = def_map[from].parent {
318        if item == parent_id {
319            // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly)
320            Some(if parent_id == DefMap::ROOT { PathKind::Crate } else { PathKind::Super(1) })
321        } else {
322            None
323        }
324    } else {
325        None
326    }
327}
328
329#[tracing::instrument(skip_all)]
330fn calculate_best_path(
331    ctx: &FindPathCtx<'_>,
332    visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
333    item: ItemInNs,
334    max_len: usize,
335    best_choice: &mut Option<Choice>,
336) {
337    let fuel = ctx.fuel.get();
338    if fuel == 0 {
339        // we ran out of fuel, so we stop searching here
340        tracing::warn!(
341            "ran out of fuel while searching for a path for item {item:?} of krate {:?} from krate {:?}",
342            item.krate(ctx.db),
343            ctx.from.krate()
344        );
345        return;
346    }
347    ctx.fuel.set(fuel - 1);
348
349    if item.krate(ctx.db) == Some(ctx.from.krate) {
350        // Item was defined in the same crate that wants to import it. It cannot be found in any
351        // dependency in this case.
352        calculate_best_path_local(ctx, visited_modules, item, max_len, best_choice)
353    } else if ctx.is_std_item {
354        // The item we are searching for comes from the sysroot libraries, so skip prefer looking in
355        // the sysroot libraries directly.
356        // We do need to fallback as the item in question could be re-exported by another crate
357        // while not being a transitive dependency of the current crate.
358        find_in_sysroot(ctx, visited_modules, item, max_len, best_choice)
359    } else {
360        // Item was defined in some upstream crate. This means that it must be exported from one,
361        // too (unless we can't name it at all). It could *also* be (re)exported by the same crate
362        // that wants to import it here, but we always prefer to use the external path here.
363
364        ctx.from.krate.data(ctx.db).dependencies.iter().for_each(|dep| {
365            find_in_dep(ctx, visited_modules, item, max_len, best_choice, dep.crate_id)
366        });
367    }
368}
369
370fn find_in_sysroot(
371    ctx: &FindPathCtx<'_>,
372    visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
373    item: ItemInNs,
374    max_len: usize,
375    best_choice: &mut Option<Choice>,
376) {
377    let dependencies = &ctx.from.krate.data(ctx.db).dependencies;
378    let mut search = |lang, best_choice: &mut _| {
379        if let Some(dep) = dependencies.iter().filter(|it| it.is_sysroot()).find(|dep| {
380            match dep.crate_id.data(ctx.db).origin {
381                CrateOrigin::Lang(l) => l == lang,
382                _ => false,
383            }
384        }) {
385            find_in_dep(ctx, visited_modules, item, max_len, best_choice, dep.crate_id);
386        }
387    };
388    if ctx.cfg.prefer_no_std {
389        search(LangCrateOrigin::Core, best_choice);
390        if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
391            return;
392        }
393        search(LangCrateOrigin::Std, best_choice);
394        if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
395            return;
396        }
397    } else {
398        search(LangCrateOrigin::Std, best_choice);
399        if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
400            return;
401        }
402        search(LangCrateOrigin::Core, best_choice);
403        if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
404            return;
405        }
406    }
407    dependencies
408        .iter()
409        .filter(|it| it.is_sysroot())
410        .chain(dependencies.iter().filter(|it| !it.is_sysroot()))
411        .for_each(|dep| {
412            find_in_dep(ctx, visited_modules, item, max_len, best_choice, dep.crate_id);
413        });
414}
415
416fn find_in_dep(
417    ctx: &FindPathCtx<'_>,
418    visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
419    item: ItemInNs,
420    max_len: usize,
421    best_choice: &mut Option<Choice>,
422    dep: Crate,
423) {
424    let import_map = ctx.db.import_map(dep);
425    let Some(import_info_for) = import_map.import_info_for(item) else {
426        return;
427    };
428    for info in import_info_for {
429        if info.is_doc_hidden {
430            // the item or import is `#[doc(hidden)]`, so skip it as it is in an external crate
431            continue;
432        }
433
434        // Determine best path for containing module and append last segment from `info`.
435        // FIXME: we should guide this to look up the path locally, or from the same crate again?
436        let choice = find_path_for_module(
437            ctx,
438            visited_modules,
439            info.container,
440            true,
441            best_choice.as_ref().map_or(max_len, |it| it.path.len()) - 1,
442        );
443        let Some(mut choice) = choice else {
444            continue;
445        };
446        cov_mark::hit!(partially_imported);
447        if info.is_unstable {
448            if !ctx.cfg.allow_unstable {
449                // the item is unstable and we are not allowed to use unstable items
450                continue;
451            }
452            choice.stability = Unstable;
453        }
454
455        Choice::try_select(best_choice, choice, ctx.cfg.prefer_prelude, info.name.clone());
456    }
457}
458
459fn calculate_best_path_local(
460    ctx: &FindPathCtx<'_>,
461    visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
462    item: ItemInNs,
463    max_len: usize,
464    best_choice: &mut Option<Choice>,
465) {
466    // FIXME: cache the `find_local_import_locations` output?
467    find_local_import_locations(
468        ctx.db,
469        item,
470        ctx.from,
471        ctx.from_def_map,
472        visited_modules,
473        |visited_modules, name, module_id| {
474            // we are looking for paths of length up to best_path_len, any longer will make it be
475            // less optimal. The -1 is due to us pushing name onto it afterwards.
476            if let Some(choice) = find_path_for_module(
477                ctx,
478                visited_modules,
479                module_id,
480                false,
481                best_choice.as_ref().map_or(max_len, |it| it.path.len()) - 1,
482            ) {
483                Choice::try_select(best_choice, choice, ctx.cfg.prefer_prelude, name.clone());
484            }
485        },
486    );
487}
488
489#[derive(Debug)]
490struct Choice {
491    path: ModPath,
492    /// The length in characters of the path
493    path_text_len: usize,
494    /// The stability of the path
495    stability: Stability,
496    /// Whether this path contains a prelude segment and preference for it has been signaled
497    prefer_due_to_prelude: bool,
498}
499
500impl Choice {
501    fn new(prefer_prelude: bool, kind: PathKind, name: Name, stability: Stability) -> Self {
502        Self {
503            path_text_len: path_kind_len(kind) + name.as_str().len(),
504            stability,
505            prefer_due_to_prelude: prefer_prelude && name == sym::prelude,
506            path: ModPath::from_segments(kind, iter::once(name)),
507        }
508    }
509
510    fn push(mut self, prefer_prelude: bool, name: Name) -> Self {
511        self.path_text_len += name.as_str().len();
512        self.prefer_due_to_prelude |= prefer_prelude && name == sym::prelude;
513        self.path.push_segment(name);
514        self
515    }
516
517    fn try_select(
518        current: &mut Option<Choice>,
519        mut other: Choice,
520        prefer_prelude: bool,
521        name: Name,
522    ) {
523        let Some(current) = current else {
524            *current = Some(other.push(prefer_prelude, name));
525            return;
526        };
527        match other
528            .stability
529            .cmp(&current.stability)
530            .then_with(|| other.prefer_due_to_prelude.cmp(&current.prefer_due_to_prelude))
531            .then_with(|| (current.path.len()).cmp(&(other.path.len() + 1)))
532        {
533            Ordering::Less => return,
534            Ordering::Equal => {
535                other.path_text_len += name.as_str().len();
536                if let Ordering::Less | Ordering::Equal =
537                    current.path_text_len.cmp(&other.path_text_len)
538                {
539                    return;
540                }
541            }
542            Ordering::Greater => {
543                other.path_text_len += name.as_str().len();
544            }
545        }
546        other.path.push_segment(name);
547        *current = other;
548    }
549}
550
551fn path_kind_len(kind: PathKind) -> usize {
552    match kind {
553        PathKind::Plain => 0,
554        PathKind::Super(0) => 4,
555        PathKind::Super(s) => s as usize * 5,
556        PathKind::Crate => 5,
557        PathKind::Abs => 2,
558        PathKind::DollarCrate(_) => 0,
559    }
560}
561
562/// Finds locations in `from.krate` from which `item` can be imported by `from`.
563fn find_local_import_locations(
564    db: &dyn DefDatabase,
565    item: ItemInNs,
566    from: ModuleId,
567    def_map: &DefMap,
568    visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
569    mut cb: impl FnMut(&mut FxHashSet<(ItemInNs, ModuleId)>, &Name, ModuleId),
570) {
571    let _p = tracing::info_span!("find_local_import_locations").entered();
572
573    // `from` can import anything below `from` with visibility of at least `from`, and anything
574    // above `from` with any visibility. That means we do not need to descend into private siblings
575    // of `from` (and similar).
576
577    // Compute the initial worklist. We start with all direct child modules of `from` as well as all
578    // of its (recursive) parent modules.
579    let mut worklist = def_map[from.local_id]
580        .children
581        .values()
582        .map(|&child| def_map.module_id(child))
583        .chain(iter::successors(from.containing_module(db), |m| m.containing_module(db)))
584        .zip(iter::repeat(false))
585        .collect::<Vec<_>>();
586
587    let def_map = def_map.crate_root().def_map(db);
588    let mut block_def_map;
589    let mut cursor = 0;
590
591    while let Some(&mut (module, ref mut processed)) = worklist.get_mut(cursor) {
592        cursor += 1;
593        if !visited_modules.insert((item, module)) {
594            // already processed this module
595            continue;
596        }
597        *processed = true;
598        let data = if module.block.is_some() {
599            // Re-query the block's DefMap
600            block_def_map = module.def_map(db);
601            &block_def_map[module.local_id]
602        } else {
603            // Reuse the root DefMap
604            &def_map[module.local_id]
605        };
606
607        if let Some((name, vis, declared)) = data.scope.name_of(item)
608            && vis.is_visible_from(db, from)
609        {
610            let is_pub_or_explicit = match vis {
611                Visibility::Module(_, VisibilityExplicitness::Explicit) => {
612                    cov_mark::hit!(explicit_private_imports);
613                    true
614                }
615                Visibility::Module(_, VisibilityExplicitness::Implicit) => {
616                    cov_mark::hit!(discount_private_imports);
617                    false
618                }
619                Visibility::PubCrate(_) => true,
620                Visibility::Public => true,
621            };
622
623            // Ignore private imports unless they are explicit. these could be used if we are
624            // in a submodule of this module, but that's usually not
625            // what the user wants; and if this module can import
626            // the item and we're a submodule of it, so can we.
627            // Also this keeps the cached data smaller.
628            if declared || is_pub_or_explicit {
629                cb(visited_modules, name, module);
630            }
631        }
632
633        // Descend into all modules visible from `from`.
634        for (module, vis) in data.scope.modules_in_scope() {
635            if module.krate != from.krate {
636                // We don't need to look at modules from other crates as our item has to be in the
637                // current crate
638                continue;
639            }
640            if visited_modules.contains(&(item, module)) {
641                continue;
642            }
643
644            if vis.is_visible_from(db, from) {
645                worklist.push((module, false));
646            }
647        }
648    }
649    worklist.into_iter().filter(|&(_, processed)| processed).for_each(|(module, _)| {
650        visited_modules.remove(&(item, module));
651    });
652}
653
654#[cfg(test)]
655mod tests {
656    use expect_test::{Expect, expect};
657    use hir_expand::db::ExpandDatabase;
658    use itertools::Itertools;
659    use span::Edition;
660    use stdx::format_to;
661    use syntax::ast::AstNode;
662    use test_fixture::WithFixture;
663
664    use crate::test_db::TestDB;
665
666    use super::*;
667
668    /// `code` needs to contain a cursor marker; checks that `find_path` for the
669    /// item the `path` refers to returns that same path when called from the
670    /// module the cursor is in.
671    #[track_caller]
672    fn check_found_path_(
673        #[rust_analyzer::rust_fixture] ra_fixture: &str,
674        path: &str,
675        prefer_prelude: bool,
676        prefer_absolute: bool,
677        prefer_no_std: bool,
678        allow_unstable: bool,
679        expect: Expect,
680    ) {
681        let (db, pos) = TestDB::with_position(ra_fixture);
682        let module = db.module_at_position(pos);
683        let parsed_path_file =
684            syntax::SourceFile::parse(&format!("use {path};"), span::Edition::CURRENT);
685        let ast_path =
686            parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
687        let mod_path = ModPath::from_src(&db, ast_path, &mut |range| {
688            db.span_map(pos.file_id.into()).as_ref().span_for_range(range).ctx
689        })
690        .unwrap();
691
692        let (def_map, local_def_map) = module.local_def_map(&db);
693        let resolved = def_map
694            .resolve_path(
695                local_def_map,
696                &db,
697                module.local_id,
698                &mod_path,
699                crate::item_scope::BuiltinShadowMode::Module,
700                None,
701            )
702            .0;
703        let resolved = resolved
704            .take_types()
705            .map(ItemInNs::Types)
706            .or_else(|| resolved.take_values().map(ItemInNs::Values))
707            .expect("path does not resolve to a type or value");
708
709        let mut res = String::new();
710        for (prefix, ignore_local_imports) in
711            [PrefixKind::Plain, PrefixKind::ByCrate, PrefixKind::BySelf]
712                .into_iter()
713                .cartesian_product([false, true])
714        {
715            let found_path = find_path(
716                &db,
717                resolved,
718                module,
719                prefix,
720                ignore_local_imports,
721                ImportPathConfig { prefer_no_std, prefer_prelude, prefer_absolute, allow_unstable },
722            );
723            format_to!(
724                res,
725                "{:7}(imports {}): {}\n",
726                format!("{:?}", prefix),
727                if ignore_local_imports { '✖' } else { '✔' },
728                found_path.map_or_else(
729                    || "<unresolvable>".to_owned(),
730                    |it| it.display(&db, Edition::CURRENT).to_string()
731                ),
732            );
733        }
734        expect.assert_eq(&res);
735    }
736
737    fn check_found_path(
738        #[rust_analyzer::rust_fixture] ra_fixture: &str,
739        path: &str,
740        expect: Expect,
741    ) {
742        check_found_path_(ra_fixture, path, false, false, false, false, expect);
743    }
744
745    fn check_found_path_prelude(
746        #[rust_analyzer::rust_fixture] ra_fixture: &str,
747        path: &str,
748        expect: Expect,
749    ) {
750        check_found_path_(ra_fixture, path, true, false, false, false, expect);
751    }
752
753    fn check_found_path_absolute(
754        #[rust_analyzer::rust_fixture] ra_fixture: &str,
755        path: &str,
756        expect: Expect,
757    ) {
758        check_found_path_(ra_fixture, path, false, true, false, false, expect);
759    }
760
761    fn check_found_path_prefer_no_std(
762        #[rust_analyzer::rust_fixture] ra_fixture: &str,
763        path: &str,
764        expect: Expect,
765    ) {
766        check_found_path_(ra_fixture, path, false, false, true, false, expect);
767    }
768
769    fn check_found_path_prefer_no_std_allow_unstable(
770        #[rust_analyzer::rust_fixture] ra_fixture: &str,
771        path: &str,
772        expect: Expect,
773    ) {
774        check_found_path_(ra_fixture, path, false, false, true, true, expect);
775    }
776
777    #[test]
778    fn same_module() {
779        check_found_path(
780            r#"
781struct S;
782$0
783        "#,
784            "S",
785            expect![[r#"
786                Plain  (imports ✔): S
787                Plain  (imports ✖): S
788                ByCrate(imports ✔): crate::S
789                ByCrate(imports ✖): crate::S
790                BySelf (imports ✔): self::S
791                BySelf (imports ✖): self::S
792            "#]],
793        );
794    }
795
796    #[test]
797    fn enum_variant() {
798        check_found_path(
799            r#"
800enum E { A }
801$0
802        "#,
803            "E::A",
804            expect![[r#"
805                Plain  (imports ✔): E::A
806                Plain  (imports ✖): E::A
807                ByCrate(imports ✔): crate::E::A
808                ByCrate(imports ✖): crate::E::A
809                BySelf (imports ✔): self::E::A
810                BySelf (imports ✖): self::E::A
811            "#]],
812        );
813    }
814
815    #[test]
816    fn sub_module() {
817        check_found_path(
818            r#"
819mod foo {
820    pub struct S;
821}
822$0
823        "#,
824            "foo::S",
825            expect![[r#"
826                Plain  (imports ✔): foo::S
827                Plain  (imports ✖): foo::S
828                ByCrate(imports ✔): crate::foo::S
829                ByCrate(imports ✖): crate::foo::S
830                BySelf (imports ✔): self::foo::S
831                BySelf (imports ✖): self::foo::S
832            "#]],
833        );
834    }
835
836    #[test]
837    fn super_module() {
838        check_found_path(
839            r#"
840//- /main.rs
841mod foo;
842//- /foo.rs
843mod bar;
844struct S;
845//- /foo/bar.rs
846$0
847        "#,
848            "super::S",
849            expect![[r#"
850                Plain  (imports ✔): super::S
851                Plain  (imports ✖): super::S
852                ByCrate(imports ✔): crate::foo::S
853                ByCrate(imports ✖): crate::foo::S
854                BySelf (imports ✔): super::S
855                BySelf (imports ✖): super::S
856            "#]],
857        );
858    }
859
860    #[test]
861    fn self_module() {
862        check_found_path(
863            r#"
864//- /main.rs
865mod foo;
866//- /foo.rs
867$0
868        "#,
869            "self",
870            expect![[r#"
871                Plain  (imports ✔): self
872                Plain  (imports ✖): self
873                ByCrate(imports ✔): crate::foo
874                ByCrate(imports ✖): crate::foo
875                BySelf (imports ✔): self
876                BySelf (imports ✖): self
877            "#]],
878        );
879    }
880
881    #[test]
882    fn crate_root() {
883        check_found_path(
884            r#"
885//- /main.rs
886mod foo;
887//- /foo.rs
888$0
889        "#,
890            "crate",
891            expect![[r#"
892                Plain  (imports ✔): crate
893                Plain  (imports ✖): crate
894                ByCrate(imports ✔): crate
895                ByCrate(imports ✖): crate
896                BySelf (imports ✔): crate
897                BySelf (imports ✖): crate
898            "#]],
899        );
900    }
901
902    #[test]
903    fn same_crate() {
904        check_found_path(
905            r#"
906//- /main.rs
907mod foo;
908struct S;
909//- /foo.rs
910$0
911        "#,
912            "crate::S",
913            expect![[r#"
914                Plain  (imports ✔): crate::S
915                Plain  (imports ✖): crate::S
916                ByCrate(imports ✔): crate::S
917                ByCrate(imports ✖): crate::S
918                BySelf (imports ✔): crate::S
919                BySelf (imports ✖): crate::S
920            "#]],
921        );
922    }
923
924    #[test]
925    fn different_crate() {
926        check_found_path(
927            r#"
928//- /main.rs crate:main deps:std
929$0
930//- /std.rs crate:std
931pub struct S;
932        "#,
933            "std::S",
934            expect![[r#"
935                Plain  (imports ✔): std::S
936                Plain  (imports ✖): std::S
937                ByCrate(imports ✔): std::S
938                ByCrate(imports ✖): std::S
939                BySelf (imports ✔): std::S
940                BySelf (imports ✖): std::S
941            "#]],
942        );
943    }
944
945    #[test]
946    fn different_crate_renamed() {
947        check_found_path(
948            r#"
949//- /main.rs crate:main deps:std
950extern crate std as std_renamed;
951$0
952//- /std.rs crate:std
953pub struct S;
954        "#,
955            "std_renamed::S",
956            expect![[r#"
957                Plain  (imports ✔): std_renamed::S
958                Plain  (imports ✖): std_renamed::S
959                ByCrate(imports ✔): std_renamed::S
960                ByCrate(imports ✖): std_renamed::S
961                BySelf (imports ✔): std_renamed::S
962                BySelf (imports ✖): std_renamed::S
963            "#]],
964        );
965    }
966
967    #[test]
968    fn partially_imported() {
969        cov_mark::check!(partially_imported);
970        // Tests that short paths are used even for external items, when parts of the path are
971        // already in scope.
972        check_found_path(
973            r#"
974//- /main.rs crate:main deps:syntax
975
976use syntax::ast;
977$0
978
979//- /lib.rs crate:syntax
980pub mod ast {
981    pub enum ModuleItem {
982        A, B, C,
983    }
984}
985        "#,
986            "syntax::ast::ModuleItem",
987            expect![[r#"
988                Plain  (imports ✔): ast::ModuleItem
989                Plain  (imports ✖): syntax::ast::ModuleItem
990                ByCrate(imports ✔): crate::ast::ModuleItem
991                ByCrate(imports ✖): syntax::ast::ModuleItem
992                BySelf (imports ✔): self::ast::ModuleItem
993                BySelf (imports ✖): syntax::ast::ModuleItem
994            "#]],
995        );
996
997        check_found_path(
998            r#"
999//- /main.rs crate:main deps:syntax
1000$0
1001
1002//- /lib.rs crate:syntax
1003pub mod ast {
1004    pub enum ModuleItem {
1005        A, B, C,
1006    }
1007}
1008        "#,
1009            "syntax::ast::ModuleItem",
1010            expect![[r#"
1011                Plain  (imports ✔): syntax::ast::ModuleItem
1012                Plain  (imports ✖): syntax::ast::ModuleItem
1013                ByCrate(imports ✔): syntax::ast::ModuleItem
1014                ByCrate(imports ✖): syntax::ast::ModuleItem
1015                BySelf (imports ✔): syntax::ast::ModuleItem
1016                BySelf (imports ✖): syntax::ast::ModuleItem
1017            "#]],
1018        );
1019    }
1020
1021    #[test]
1022    fn partially_imported_with_prefer_absolute() {
1023        cov_mark::check!(partially_imported);
1024        // Similar to partially_imported test case above, but with prefer_absolute enabled.
1025        // Even if the actual imported item is in external crate, if the path to that item
1026        // is starting from the imported name, then the path should not start from "::".
1027        // i.e. The first line in the expected output should not start from "::".
1028        check_found_path_absolute(
1029            r#"
1030//- /main.rs crate:main deps:syntax
1031
1032use syntax::ast;
1033$0
1034
1035//- /lib.rs crate:syntax
1036pub mod ast {
1037    pub enum ModuleItem {
1038        A, B, C,
1039    }
1040}
1041        "#,
1042            "syntax::ast::ModuleItem",
1043            expect![[r#"
1044                Plain  (imports ✔): ast::ModuleItem
1045                Plain  (imports ✖): ::syntax::ast::ModuleItem
1046                ByCrate(imports ✔): crate::ast::ModuleItem
1047                ByCrate(imports ✖): ::syntax::ast::ModuleItem
1048                BySelf (imports ✔): self::ast::ModuleItem
1049                BySelf (imports ✖): ::syntax::ast::ModuleItem
1050            "#]],
1051        );
1052    }
1053
1054    #[test]
1055    fn same_crate_reexport() {
1056        check_found_path(
1057            r#"
1058mod bar {
1059    mod foo { pub(crate) struct S; }
1060    pub(crate) use foo::*;
1061}
1062$0
1063        "#,
1064            "bar::S",
1065            expect![[r#"
1066                Plain  (imports ✔): bar::S
1067                Plain  (imports ✖): bar::S
1068                ByCrate(imports ✔): crate::bar::S
1069                ByCrate(imports ✖): crate::bar::S
1070                BySelf (imports ✔): self::bar::S
1071                BySelf (imports ✖): self::bar::S
1072            "#]],
1073        );
1074    }
1075
1076    #[test]
1077    fn same_crate_reexport_rename() {
1078        check_found_path(
1079            r#"
1080mod bar {
1081    mod foo { pub(crate) struct S; }
1082    pub(crate) use foo::S as U;
1083}
1084$0
1085        "#,
1086            "bar::U",
1087            expect![[r#"
1088                Plain  (imports ✔): bar::U
1089                Plain  (imports ✖): bar::U
1090                ByCrate(imports ✔): crate::bar::U
1091                ByCrate(imports ✖): crate::bar::U
1092                BySelf (imports ✔): self::bar::U
1093                BySelf (imports ✖): self::bar::U
1094            "#]],
1095        );
1096    }
1097
1098    #[test]
1099    fn different_crate_reexport() {
1100        check_found_path(
1101            r#"
1102//- /main.rs crate:main deps:std
1103$0
1104//- /std.rs crate:std deps:core
1105pub use core::S;
1106//- /core.rs crate:core
1107pub struct S;
1108        "#,
1109            "std::S",
1110            expect![[r#"
1111                Plain  (imports ✔): std::S
1112                Plain  (imports ✖): std::S
1113                ByCrate(imports ✔): std::S
1114                ByCrate(imports ✖): std::S
1115                BySelf (imports ✔): std::S
1116                BySelf (imports ✖): std::S
1117            "#]],
1118        );
1119    }
1120
1121    #[test]
1122    fn prelude() {
1123        check_found_path(
1124            r#"
1125//- /main.rs edition:2018 crate:main deps:std
1126$0
1127//- /std.rs crate:std
1128pub mod prelude {
1129    pub mod rust_2018 {
1130        pub struct S;
1131    }
1132}
1133        "#,
1134            "S",
1135            expect![[r#"
1136                Plain  (imports ✔): S
1137                Plain  (imports ✖): S
1138                ByCrate(imports ✔): S
1139                ByCrate(imports ✖): S
1140                BySelf (imports ✔): S
1141                BySelf (imports ✖): S
1142            "#]],
1143        );
1144    }
1145
1146    #[test]
1147    fn shadowed_prelude() {
1148        check_found_path(
1149            r#"
1150//- /main.rs crate:main deps:std
1151struct S;
1152$0
1153//- /std.rs crate:std
1154pub mod prelude {
1155    pub mod rust_2018 {
1156        pub struct S;
1157    }
1158}
1159"#,
1160            "std::prelude::rust_2018::S",
1161            expect![[r#"
1162                Plain  (imports ✔): std::prelude::rust_2018::S
1163                Plain  (imports ✖): std::prelude::rust_2018::S
1164                ByCrate(imports ✔): std::prelude::rust_2018::S
1165                ByCrate(imports ✖): std::prelude::rust_2018::S
1166                BySelf (imports ✔): std::prelude::rust_2018::S
1167                BySelf (imports ✖): std::prelude::rust_2018::S
1168            "#]],
1169        );
1170    }
1171
1172    #[test]
1173    fn imported_prelude() {
1174        check_found_path(
1175            r#"
1176//- /main.rs edition:2018 crate:main deps:std
1177use S;
1178$0
1179//- /std.rs crate:std
1180pub mod prelude {
1181    pub mod rust_2018 {
1182        pub struct S;
1183    }
1184}
1185"#,
1186            "S",
1187            expect![[r#"
1188                Plain  (imports ✔): S
1189                Plain  (imports ✖): S
1190                ByCrate(imports ✔): crate::S
1191                ByCrate(imports ✖): S
1192                BySelf (imports ✔): self::S
1193                BySelf (imports ✖): S
1194            "#]],
1195        );
1196    }
1197
1198    #[test]
1199    fn enum_variant_from_prelude() {
1200        let code = r#"
1201//- /main.rs edition:2018 crate:main deps:std
1202$0
1203//- /std.rs crate:std
1204pub mod prelude {
1205    pub mod rust_2018 {
1206        pub enum Option<T> { Some(T), None }
1207        pub use Option::*;
1208    }
1209}
1210        "#;
1211        check_found_path(
1212            code,
1213            "None",
1214            expect![[r#"
1215                Plain  (imports ✔): None
1216                Plain  (imports ✖): None
1217                ByCrate(imports ✔): None
1218                ByCrate(imports ✖): None
1219                BySelf (imports ✔): None
1220                BySelf (imports ✖): None
1221            "#]],
1222        );
1223        check_found_path(
1224            code,
1225            "Some",
1226            expect![[r#"
1227                Plain  (imports ✔): Some
1228                Plain  (imports ✖): Some
1229                ByCrate(imports ✔): Some
1230                ByCrate(imports ✖): Some
1231                BySelf (imports ✔): Some
1232                BySelf (imports ✖): Some
1233            "#]],
1234        );
1235    }
1236
1237    #[test]
1238    fn shortest_path() {
1239        check_found_path(
1240            r#"
1241//- /main.rs
1242pub mod foo;
1243pub mod baz;
1244struct S;
1245$0
1246//- /foo.rs
1247pub mod bar { pub struct S; }
1248//- /baz.rs
1249pub use crate::foo::bar::S;
1250        "#,
1251            "baz::S",
1252            expect![[r#"
1253                Plain  (imports ✔): baz::S
1254                Plain  (imports ✖): baz::S
1255                ByCrate(imports ✔): crate::baz::S
1256                ByCrate(imports ✖): crate::baz::S
1257                BySelf (imports ✔): self::baz::S
1258                BySelf (imports ✖): self::baz::S
1259            "#]],
1260        );
1261    }
1262
1263    #[test]
1264    fn discount_private_imports() {
1265        cov_mark::check!(discount_private_imports);
1266        check_found_path(
1267            r#"
1268//- /main.rs
1269mod foo;
1270pub mod bar { pub struct S; }
1271use bar::S;
1272//- /foo.rs
1273$0
1274        "#,
1275            // crate::S would be shorter, but using private imports seems wrong
1276            "crate::bar::S",
1277            expect![[r#"
1278                Plain  (imports ✔): crate::bar::S
1279                Plain  (imports ✖): crate::bar::S
1280                ByCrate(imports ✔): crate::bar::S
1281                ByCrate(imports ✖): crate::bar::S
1282                BySelf (imports ✔): crate::bar::S
1283                BySelf (imports ✖): crate::bar::S
1284            "#]],
1285        );
1286    }
1287
1288    #[test]
1289    fn explicit_private_imports_crate() {
1290        check_found_path(
1291            r#"
1292//- /main.rs
1293mod foo;
1294pub mod bar { pub struct S; }
1295pub(crate) use bar::S;
1296//- /foo.rs
1297$0
1298        "#,
1299            "crate::S",
1300            expect![[r#"
1301                Plain  (imports ✔): crate::S
1302                Plain  (imports ✖): crate::S
1303                ByCrate(imports ✔): crate::S
1304                ByCrate(imports ✖): crate::S
1305                BySelf (imports ✔): crate::S
1306                BySelf (imports ✖): crate::S
1307            "#]],
1308        );
1309    }
1310
1311    #[test]
1312    fn explicit_private_imports() {
1313        cov_mark::check!(explicit_private_imports);
1314        check_found_path(
1315            r#"
1316//- /main.rs
1317pub mod bar {
1318    mod foo;
1319    pub mod baz { pub struct S; }
1320    pub(self) use baz::S;
1321}
1322
1323//- /bar/foo.rs
1324$0
1325        "#,
1326            "super::S",
1327            expect![[r#"
1328                Plain  (imports ✔): super::S
1329                Plain  (imports ✖): super::S
1330                ByCrate(imports ✔): crate::bar::S
1331                ByCrate(imports ✖): crate::bar::S
1332                BySelf (imports ✔): super::S
1333                BySelf (imports ✖): super::S
1334            "#]],
1335        );
1336    }
1337
1338    #[test]
1339    fn import_cycle() {
1340        check_found_path(
1341            r#"
1342//- /main.rs
1343pub mod foo;
1344pub mod bar;
1345pub mod baz;
1346//- /bar.rs
1347$0
1348//- /foo.rs
1349pub use super::baz;
1350pub struct S;
1351//- /baz.rs
1352pub use super::foo;
1353        "#,
1354            "crate::foo::S",
1355            expect![[r#"
1356                Plain  (imports ✔): crate::foo::S
1357                Plain  (imports ✖): crate::foo::S
1358                ByCrate(imports ✔): crate::foo::S
1359                ByCrate(imports ✖): crate::foo::S
1360                BySelf (imports ✔): crate::foo::S
1361                BySelf (imports ✖): crate::foo::S
1362            "#]],
1363        );
1364    }
1365
1366    #[test]
1367    fn prefer_std_paths_over_alloc() {
1368        check_found_path(
1369            r#"
1370//- /main.rs crate:main deps:alloc,std
1371$0
1372
1373//- /std.rs crate:std deps:alloc
1374pub mod sync {
1375    pub use alloc::sync::Arc;
1376}
1377
1378//- /zzz.rs crate:alloc
1379pub mod sync {
1380    pub struct Arc;
1381}
1382        "#,
1383            "std::sync::Arc",
1384            expect![[r#"
1385                Plain  (imports ✔): std::sync::Arc
1386                Plain  (imports ✖): std::sync::Arc
1387                ByCrate(imports ✔): std::sync::Arc
1388                ByCrate(imports ✖): std::sync::Arc
1389                BySelf (imports ✔): std::sync::Arc
1390                BySelf (imports ✖): std::sync::Arc
1391            "#]],
1392        );
1393    }
1394    #[test]
1395    fn prefer_core_paths_over_std_for_mod_reexport() {
1396        check_found_path_prefer_no_std(
1397            r#"
1398//- /main.rs crate:main deps:core,std
1399
1400$0
1401
1402//- /stdlib.rs crate:std deps:core
1403
1404pub use core::pin;
1405
1406//- /corelib.rs crate:core
1407
1408pub mod pin {
1409    pub struct Pin;
1410}
1411            "#,
1412            "std::pin::Pin",
1413            expect![[r#"
1414                Plain  (imports ✔): core::pin::Pin
1415                Plain  (imports ✖): core::pin::Pin
1416                ByCrate(imports ✔): core::pin::Pin
1417                ByCrate(imports ✖): core::pin::Pin
1418                BySelf (imports ✔): core::pin::Pin
1419                BySelf (imports ✖): core::pin::Pin
1420            "#]],
1421        );
1422    }
1423
1424    #[test]
1425    fn prefer_core_paths_over_std() {
1426        check_found_path_prefer_no_std(
1427            r#"
1428//- /main.rs crate:main deps:core,std
1429
1430$0
1431
1432//- /std.rs crate:std deps:core
1433
1434pub mod fmt {
1435    pub use core::fmt::Error;
1436}
1437
1438//- /zzz.rs crate:core
1439
1440pub mod fmt {
1441    pub struct Error;
1442}
1443        "#,
1444            "core::fmt::Error",
1445            expect![[r#"
1446                Plain  (imports ✔): core::fmt::Error
1447                Plain  (imports ✖): core::fmt::Error
1448                ByCrate(imports ✔): core::fmt::Error
1449                ByCrate(imports ✖): core::fmt::Error
1450                BySelf (imports ✔): core::fmt::Error
1451                BySelf (imports ✖): core::fmt::Error
1452            "#]],
1453        );
1454        check_found_path(
1455            r#"
1456//- /main.rs crate:main deps:core,std
1457#![no_std]
1458
1459$0
1460
1461//- /std.rs crate:std deps:core
1462
1463pub mod fmt {
1464    pub use core::fmt::Error;
1465}
1466
1467//- /zzz.rs crate:core
1468
1469pub mod fmt {
1470    pub struct Error;
1471}
1472        "#,
1473            "core::fmt::Error",
1474            expect![[r#"
1475                Plain  (imports ✔): core::fmt::Error
1476                Plain  (imports ✖): core::fmt::Error
1477                ByCrate(imports ✔): core::fmt::Error
1478                ByCrate(imports ✖): core::fmt::Error
1479                BySelf (imports ✔): core::fmt::Error
1480                BySelf (imports ✖): core::fmt::Error
1481            "#]],
1482        );
1483
1484        // Should also work (on a best-effort basis) if `no_std` is conditional.
1485        check_found_path(
1486            r#"
1487//- /main.rs crate:main deps:core,std
1488#![cfg_attr(not(test), no_std)]
1489
1490$0
1491
1492//- /std.rs crate:std deps:core
1493
1494pub mod fmt {
1495    pub use core::fmt::Error;
1496}
1497
1498//- /zzz.rs crate:core
1499
1500pub mod fmt {
1501    pub struct Error;
1502}
1503        "#,
1504            "core::fmt::Error",
1505            expect![[r#"
1506                Plain  (imports ✔): core::fmt::Error
1507                Plain  (imports ✖): core::fmt::Error
1508                ByCrate(imports ✔): core::fmt::Error
1509                ByCrate(imports ✖): core::fmt::Error
1510                BySelf (imports ✔): core::fmt::Error
1511                BySelf (imports ✖): core::fmt::Error
1512            "#]],
1513        );
1514    }
1515
1516    #[test]
1517    fn prefer_alloc_paths_over_std() {
1518        check_found_path(
1519            r#"
1520//- /main.rs crate:main deps:alloc,std
1521#![no_std]
1522
1523extern crate alloc;
1524
1525$0
1526
1527//- /std.rs crate:std deps:alloc
1528
1529pub mod sync {
1530    pub use alloc::sync::Arc;
1531}
1532
1533//- /zzz.rs crate:alloc
1534
1535pub mod sync {
1536    pub struct Arc;
1537}
1538            "#,
1539            "alloc::sync::Arc",
1540            expect![[r#"
1541                Plain  (imports ✔): alloc::sync::Arc
1542                Plain  (imports ✖): alloc::sync::Arc
1543                ByCrate(imports ✔): alloc::sync::Arc
1544                ByCrate(imports ✖): alloc::sync::Arc
1545                BySelf (imports ✔): alloc::sync::Arc
1546                BySelf (imports ✖): alloc::sync::Arc
1547            "#]],
1548        );
1549    }
1550
1551    #[test]
1552    fn prefer_shorter_paths_if_not_alloc() {
1553        check_found_path(
1554            r#"
1555//- /main.rs crate:main deps:megaalloc,std
1556$0
1557
1558//- /std.rs crate:std deps:megaalloc
1559pub mod sync {
1560    pub use megaalloc::sync::Arc;
1561}
1562
1563//- /zzz.rs crate:megaalloc
1564pub struct Arc;
1565            "#,
1566            "megaalloc::Arc",
1567            expect![[r#"
1568                Plain  (imports ✔): megaalloc::Arc
1569                Plain  (imports ✖): megaalloc::Arc
1570                ByCrate(imports ✔): megaalloc::Arc
1571                ByCrate(imports ✖): megaalloc::Arc
1572                BySelf (imports ✔): megaalloc::Arc
1573                BySelf (imports ✖): megaalloc::Arc
1574            "#]],
1575        );
1576    }
1577
1578    #[test]
1579    fn builtins_are_in_scope() {
1580        let code = r#"
1581$0
1582
1583pub mod primitive {
1584    pub use u8;
1585}
1586        "#;
1587        check_found_path(
1588            code,
1589            "u8",
1590            expect![[r#"
1591                Plain  (imports ✔): u8
1592                Plain  (imports ✖): u8
1593                ByCrate(imports ✔): u8
1594                ByCrate(imports ✖): u8
1595                BySelf (imports ✔): u8
1596                BySelf (imports ✖): u8
1597            "#]],
1598        );
1599        check_found_path(
1600            code,
1601            "u16",
1602            expect![[r#"
1603                Plain  (imports ✔): u16
1604                Plain  (imports ✖): u16
1605                ByCrate(imports ✔): u16
1606                ByCrate(imports ✖): u16
1607                BySelf (imports ✔): u16
1608                BySelf (imports ✖): u16
1609            "#]],
1610        );
1611    }
1612
1613    #[test]
1614    fn inner_items() {
1615        check_found_path(
1616            r#"
1617fn main() {
1618    struct Inner {}
1619    $0
1620}
1621        "#,
1622            "Inner",
1623            expect![[r#"
1624                Plain  (imports ✔): Inner
1625                Plain  (imports ✖): Inner
1626                ByCrate(imports ✔): Inner
1627                ByCrate(imports ✖): Inner
1628                BySelf (imports ✔): Inner
1629                BySelf (imports ✖): Inner
1630            "#]],
1631        );
1632    }
1633
1634    #[test]
1635    fn inner_items_from_outer_scope() {
1636        check_found_path(
1637            r#"
1638fn main() {
1639    struct Struct {}
1640    {
1641        $0
1642    }
1643}
1644        "#,
1645            "Struct",
1646            expect![[r#"
1647                Plain  (imports ✔): Struct
1648                Plain  (imports ✖): Struct
1649                ByCrate(imports ✔): Struct
1650                ByCrate(imports ✖): Struct
1651                BySelf (imports ✔): Struct
1652                BySelf (imports ✖): Struct
1653            "#]],
1654        );
1655    }
1656
1657    #[test]
1658    fn inner_items_from_inner_module() {
1659        check_found_path(
1660            r#"
1661fn main() {
1662    mod module {
1663        pub struct Struct {}
1664    }
1665    {
1666        $0
1667    }
1668}
1669        "#,
1670            "module::Struct",
1671            expect![[r#"
1672                Plain  (imports ✔): module::Struct
1673                Plain  (imports ✖): module::Struct
1674                ByCrate(imports ✔): module::Struct
1675                ByCrate(imports ✖): module::Struct
1676                BySelf (imports ✔): module::Struct
1677                BySelf (imports ✖): module::Struct
1678            "#]],
1679        );
1680    }
1681
1682    #[test]
1683    fn outer_items_with_inner_items_present() {
1684        check_found_path(
1685            r#"
1686mod module {
1687    pub struct CompleteMe;
1688}
1689
1690fn main() {
1691    fn inner() {}
1692    $0
1693}
1694            "#,
1695            "module::CompleteMe",
1696            expect![[r#"
1697                Plain  (imports ✔): module::CompleteMe
1698                Plain  (imports ✖): module::CompleteMe
1699                ByCrate(imports ✔): crate::module::CompleteMe
1700                ByCrate(imports ✖): crate::module::CompleteMe
1701                BySelf (imports ✔): self::module::CompleteMe
1702                BySelf (imports ✖): self::module::CompleteMe
1703            "#]],
1704        )
1705    }
1706
1707    #[test]
1708    fn from_inside_module() {
1709        check_found_path(
1710            r#"
1711mod baz {
1712    pub struct Foo {}
1713}
1714
1715mod bar {
1716    fn bar() {
1717        $0
1718    }
1719}
1720            "#,
1721            "crate::baz::Foo",
1722            expect![[r#"
1723                Plain  (imports ✔): crate::baz::Foo
1724                Plain  (imports ✖): crate::baz::Foo
1725                ByCrate(imports ✔): crate::baz::Foo
1726                ByCrate(imports ✖): crate::baz::Foo
1727                BySelf (imports ✔): crate::baz::Foo
1728                BySelf (imports ✖): crate::baz::Foo
1729            "#]],
1730        )
1731    }
1732
1733    #[test]
1734    fn from_inside_module2() {
1735        check_found_path(
1736            r#"
1737mod qux {
1738    pub mod baz {
1739        pub struct Foo {}
1740    }
1741
1742    mod bar {
1743        fn bar() {
1744            $0;
1745        }
1746    }
1747}
1748
1749            "#,
1750            "crate::qux::baz::Foo",
1751            expect![[r#"
1752                Plain  (imports ✔): super::baz::Foo
1753                Plain  (imports ✖): super::baz::Foo
1754                ByCrate(imports ✔): crate::qux::baz::Foo
1755                ByCrate(imports ✖): crate::qux::baz::Foo
1756                BySelf (imports ✔): super::baz::Foo
1757                BySelf (imports ✖): super::baz::Foo
1758            "#]],
1759        )
1760    }
1761
1762    #[test]
1763    fn from_inside_module_with_inner_items() {
1764        check_found_path(
1765            r#"
1766mod baz {
1767    pub struct Foo {}
1768}
1769
1770mod bar {
1771    fn bar() {
1772        fn inner() {}
1773        $0
1774    }
1775}
1776            "#,
1777            "crate::baz::Foo",
1778            expect![[r#"
1779                Plain  (imports ✔): crate::baz::Foo
1780                Plain  (imports ✖): crate::baz::Foo
1781                ByCrate(imports ✔): crate::baz::Foo
1782                ByCrate(imports ✖): crate::baz::Foo
1783                BySelf (imports ✔): crate::baz::Foo
1784                BySelf (imports ✖): crate::baz::Foo
1785            "#]],
1786        )
1787    }
1788
1789    #[test]
1790    fn recursive_pub_mod_reexport() {
1791        check_found_path(
1792            r#"
1793fn main() {
1794    let _ = 22_i32.as_name$0();
1795}
1796
1797pub mod name {
1798    pub trait AsName {
1799        fn as_name(&self) -> String;
1800    }
1801    impl AsName for i32 {
1802        fn as_name(&self) -> String {
1803            format!("Name: {}", self)
1804        }
1805    }
1806    pub use crate::name;
1807}
1808"#,
1809            "name::AsName",
1810            expect![[r#"
1811                Plain  (imports ✔): name::AsName
1812                Plain  (imports ✖): name::AsName
1813                ByCrate(imports ✔): crate::name::AsName
1814                ByCrate(imports ✖): crate::name::AsName
1815                BySelf (imports ✔): self::name::AsName
1816                BySelf (imports ✖): self::name::AsName
1817            "#]],
1818        );
1819    }
1820
1821    #[test]
1822    fn extern_crate() {
1823        check_found_path(
1824            r#"
1825//- /main.rs crate:main deps:dep
1826$0
1827//- /dep.rs crate:dep
1828"#,
1829            "dep",
1830            expect![[r#"
1831                Plain  (imports ✔): dep
1832                Plain  (imports ✖): dep
1833                ByCrate(imports ✔): dep
1834                ByCrate(imports ✖): dep
1835                BySelf (imports ✔): dep
1836                BySelf (imports ✖): dep
1837            "#]],
1838        );
1839
1840        check_found_path(
1841            r#"
1842//- /main.rs crate:main deps:dep
1843fn f() {
1844    fn inner() {}
1845    $0
1846}
1847//- /dep.rs crate:dep
1848"#,
1849            "dep",
1850            expect![[r#"
1851                Plain  (imports ✔): dep
1852                Plain  (imports ✖): dep
1853                ByCrate(imports ✔): dep
1854                ByCrate(imports ✖): dep
1855                BySelf (imports ✔): dep
1856                BySelf (imports ✖): dep
1857            "#]],
1858        );
1859    }
1860
1861    #[test]
1862    fn prelude_with_inner_items() {
1863        check_found_path(
1864            r#"
1865//- /main.rs edition:2018 crate:main deps:std
1866fn f() {
1867    fn inner() {}
1868    $0
1869}
1870//- /std.rs crate:std
1871pub mod prelude {
1872    pub mod rust_2018 {
1873        pub enum Option { None }
1874        pub use Option::*;
1875    }
1876}
1877        "#,
1878            "None",
1879            expect![[r#"
1880                Plain  (imports ✔): None
1881                Plain  (imports ✖): None
1882                ByCrate(imports ✔): None
1883                ByCrate(imports ✖): None
1884                BySelf (imports ✔): None
1885                BySelf (imports ✖): None
1886            "#]],
1887        );
1888    }
1889
1890    #[test]
1891    fn different_crate_renamed_through_dep() {
1892        check_found_path(
1893            r#"
1894//- /main.rs crate:main deps:intermediate
1895$0
1896//- /intermediate.rs crate:intermediate deps:std
1897pub extern crate std as std_renamed;
1898//- /std.rs crate:std
1899pub struct S;
1900    "#,
1901            "intermediate::std_renamed::S",
1902            expect![[r#"
1903                Plain  (imports ✔): intermediate::std_renamed::S
1904                Plain  (imports ✖): intermediate::std_renamed::S
1905                ByCrate(imports ✔): intermediate::std_renamed::S
1906                ByCrate(imports ✖): intermediate::std_renamed::S
1907                BySelf (imports ✔): intermediate::std_renamed::S
1908                BySelf (imports ✖): intermediate::std_renamed::S
1909            "#]],
1910        );
1911    }
1912
1913    #[test]
1914    fn different_crate_doc_hidden() {
1915        check_found_path(
1916            r#"
1917//- /main.rs crate:main deps:intermediate
1918$0
1919//- /intermediate.rs crate:intermediate deps:std
1920#[doc(hidden)]
1921pub extern crate std;
1922pub extern crate std as longer;
1923//- /std.rs crate:std
1924pub struct S;
1925    "#,
1926            "intermediate::longer::S",
1927            expect![[r#"
1928                Plain  (imports ✔): intermediate::longer::S
1929                Plain  (imports ✖): intermediate::longer::S
1930                ByCrate(imports ✔): intermediate::longer::S
1931                ByCrate(imports ✖): intermediate::longer::S
1932                BySelf (imports ✔): intermediate::longer::S
1933                BySelf (imports ✖): intermediate::longer::S
1934            "#]],
1935        );
1936    }
1937
1938    #[test]
1939    fn respect_doc_hidden() {
1940        check_found_path(
1941            r#"
1942//- /main.rs crate:main deps:std,lazy_static
1943$0
1944//- /lazy_static.rs crate:lazy_static deps:core
1945#[doc(hidden)]
1946pub use core::ops::Deref as __Deref;
1947//- /std.rs crate:std deps:core
1948pub use core::ops;
1949//- /core.rs crate:core
1950pub mod ops {
1951    pub trait Deref {}
1952}
1953    "#,
1954            "std::ops::Deref",
1955            expect![[r#"
1956                Plain  (imports ✔): std::ops::Deref
1957                Plain  (imports ✖): std::ops::Deref
1958                ByCrate(imports ✔): std::ops::Deref
1959                ByCrate(imports ✖): std::ops::Deref
1960                BySelf (imports ✔): std::ops::Deref
1961                BySelf (imports ✖): std::ops::Deref
1962            "#]],
1963        );
1964    }
1965
1966    #[test]
1967    fn respect_unstable_modules() {
1968        check_found_path_prefer_no_std_allow_unstable(
1969            r#"
1970//- /main.rs crate:main deps:std,core
1971extern crate std;
1972$0
1973//- /longer.rs crate:std deps:core
1974pub mod error {
1975    pub use core::error::Error;
1976}
1977//- /core.rs crate:core
1978pub mod error {
1979    #![unstable(feature = "error_in_core", issue = "103765")]
1980    pub trait Error {}
1981}
1982"#,
1983            "std::error::Error",
1984            expect![[r#"
1985                Plain  (imports ✔): std::error::Error
1986                Plain  (imports ✖): std::error::Error
1987                ByCrate(imports ✔): std::error::Error
1988                ByCrate(imports ✖): std::error::Error
1989                BySelf (imports ✔): std::error::Error
1990                BySelf (imports ✖): std::error::Error
1991            "#]],
1992        );
1993    }
1994
1995    #[test]
1996    fn respects_prelude_setting() {
1997        let ra_fixture = r#"
1998//- /main.rs crate:main deps:krate
1999$0
2000//- /krate.rs crate:krate
2001pub mod prelude {
2002    pub use crate::foo::*;
2003}
2004
2005pub mod foo {
2006    pub struct Foo;
2007}
2008"#;
2009        check_found_path(
2010            ra_fixture,
2011            "krate::foo::Foo",
2012            expect![[r#"
2013                Plain  (imports ✔): krate::foo::Foo
2014                Plain  (imports ✖): krate::foo::Foo
2015                ByCrate(imports ✔): krate::foo::Foo
2016                ByCrate(imports ✖): krate::foo::Foo
2017                BySelf (imports ✔): krate::foo::Foo
2018                BySelf (imports ✖): krate::foo::Foo
2019            "#]],
2020        );
2021        check_found_path_prelude(
2022            ra_fixture,
2023            "krate::prelude::Foo",
2024            expect![[r#"
2025                Plain  (imports ✔): krate::prelude::Foo
2026                Plain  (imports ✖): krate::prelude::Foo
2027                ByCrate(imports ✔): krate::prelude::Foo
2028                ByCrate(imports ✖): krate::prelude::Foo
2029                BySelf (imports ✔): krate::prelude::Foo
2030                BySelf (imports ✖): krate::prelude::Foo
2031            "#]],
2032        );
2033    }
2034
2035    #[test]
2036    fn respects_absolute_setting() {
2037        let ra_fixture = r#"
2038//- /main.rs crate:main deps:krate
2039$0
2040//- /krate.rs crate:krate
2041pub mod foo {
2042    pub struct Foo;
2043}
2044"#;
2045        check_found_path(
2046            ra_fixture,
2047            "krate::foo::Foo",
2048            expect![[r#"
2049            Plain  (imports ✔): krate::foo::Foo
2050            Plain  (imports ✖): krate::foo::Foo
2051            ByCrate(imports ✔): krate::foo::Foo
2052            ByCrate(imports ✖): krate::foo::Foo
2053            BySelf (imports ✔): krate::foo::Foo
2054            BySelf (imports ✖): krate::foo::Foo
2055        "#]],
2056        );
2057
2058        check_found_path_absolute(
2059            ra_fixture,
2060            "krate::foo::Foo",
2061            expect![[r#"
2062            Plain  (imports ✔): ::krate::foo::Foo
2063            Plain  (imports ✖): ::krate::foo::Foo
2064            ByCrate(imports ✔): ::krate::foo::Foo
2065            ByCrate(imports ✖): ::krate::foo::Foo
2066            BySelf (imports ✔): ::krate::foo::Foo
2067            BySelf (imports ✖): ::krate::foo::Foo
2068        "#]],
2069        );
2070    }
2071
2072    #[test]
2073    fn respect_segment_length() {
2074        check_found_path(
2075            r#"
2076//- /main.rs crate:main deps:petgraph
2077$0
2078//- /petgraph.rs crate:petgraph
2079pub mod graph {
2080    pub use crate::graph_impl::{
2081        NodeIndex
2082    };
2083}
2084
2085mod graph_impl {
2086    pub struct NodeIndex<Ix>(Ix);
2087}
2088
2089pub mod stable_graph {
2090    #[doc(no_inline)]
2091    pub use crate::graph::{NodeIndex};
2092}
2093
2094pub mod prelude {
2095    #[doc(no_inline)]
2096    pub use crate::graph::{NodeIndex};
2097}
2098"#,
2099            "petgraph::graph::NodeIndex",
2100            expect![[r#"
2101                Plain  (imports ✔): petgraph::graph::NodeIndex
2102                Plain  (imports ✖): petgraph::graph::NodeIndex
2103                ByCrate(imports ✔): petgraph::graph::NodeIndex
2104                ByCrate(imports ✖): petgraph::graph::NodeIndex
2105                BySelf (imports ✔): petgraph::graph::NodeIndex
2106                BySelf (imports ✖): petgraph::graph::NodeIndex
2107            "#]],
2108        );
2109    }
2110
2111    #[test]
2112    fn regression_17271() {
2113        check_found_path(
2114            r#"
2115//- /lib.rs crate:main
2116mod foo;
2117
2118//- /foo.rs
2119mod bar;
2120
2121pub fn b() {$0}
2122//- /foo/bar.rs
2123pub fn c() {}
2124"#,
2125            "bar::c",
2126            expect![[r#"
2127                Plain  (imports ✔): bar::c
2128                Plain  (imports ✖): bar::c
2129                ByCrate(imports ✔): crate::foo::bar::c
2130                ByCrate(imports ✖): crate::foo::bar::c
2131                BySelf (imports ✔): self::bar::c
2132                BySelf (imports ✖): self::bar::c
2133            "#]],
2134        );
2135    }
2136
2137    #[test]
2138    fn prefer_long_std_over_short_extern() {
2139        check_found_path(
2140            r#"
2141//- /lib.rs crate:main deps:futures_lite,std,core
2142$0
2143//- /futures_lite.rs crate:futures_lite deps:std,core
2144pub use crate::future::Future;
2145pub mod future {
2146    pub use core::future::Future;
2147}
2148//- /std.rs crate:std deps:core
2149pub use core::future;
2150//- /core.rs crate:core
2151pub mod future {
2152    pub trait Future {}
2153}
2154"#,
2155            "core::future::Future",
2156            expect![[r#"
2157                Plain  (imports ✔): std::future::Future
2158                Plain  (imports ✖): std::future::Future
2159                ByCrate(imports ✔): std::future::Future
2160                ByCrate(imports ✖): std::future::Future
2161                BySelf (imports ✔): std::future::Future
2162                BySelf (imports ✖): std::future::Future
2163            "#]],
2164        );
2165    }
2166}