]> git.lizzy.rs Git - rust.git/blob - crates/hir/src/source_analyzer.rs
feat: Add very simplistic ident completion for format_args! macro input
[rust.git] / crates / hir / src / source_analyzer.rs
1 //! Lookup hir elements using positions in the source code. This is a lossy
2 //! transformation: in general, a single source might correspond to several
3 //! modules, functions, etc, due to macros, cfgs and `#[path=]` attributes on
4 //! modules.
5 //!
6 //! So, this modules should not be used during hir construction, it exists
7 //! purely for "IDE needs".
8 use std::{
9     iter::{self, once},
10     sync::Arc,
11 };
12
13 use hir_def::{
14     body::{
15         self,
16         scope::{ExprScopes, ScopeId},
17         Body, BodySourceMap,
18     },
19     expr::{ExprId, Pat, PatId},
20     path::{ModPath, Path, PathKind},
21     resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
22     AsMacroCall, DefWithBodyId, FieldId, FunctionId, LocalFieldId, ModuleDefId, VariantId,
23 };
24 use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
25 use hir_ty::{
26     diagnostics::{record_literal_missing_fields, record_pattern_missing_fields},
27     InferenceResult, Interner, Substitution, TyExt, TyLoweringContext,
28 };
29 use syntax::{
30     ast::{self, AstNode},
31     SyntaxKind, SyntaxNode, TextRange, TextSize,
32 };
33
34 use crate::{
35     db::HirDatabase, semantics::PathResolution, Adt, BuiltinAttr, BuiltinType, Const, Field,
36     Function, Local, MacroDef, ModuleDef, Static, Struct, ToolModule, Trait, Type, TypeAlias,
37     TypeParam, Variant,
38 };
39 use base_db::CrateId;
40
41 /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
42 /// original source files. It should not be used inside the HIR itself.
43 #[derive(Debug)]
44 pub(crate) struct SourceAnalyzer {
45     pub(crate) file_id: HirFileId,
46     pub(crate) resolver: Resolver,
47     body: Option<Arc<Body>>,
48     body_source_map: Option<Arc<BodySourceMap>>,
49     infer: Option<Arc<InferenceResult>>,
50 }
51
52 impl SourceAnalyzer {
53     pub(crate) fn new_for_body(
54         db: &dyn HirDatabase,
55         def: DefWithBodyId,
56         node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
57         offset: Option<TextSize>,
58     ) -> SourceAnalyzer {
59         let (body, source_map) = db.body_with_source_map(def);
60         let scopes = db.expr_scopes(def);
61         let scope = match offset {
62             None => scope_for(&scopes, &source_map, node),
63             Some(offset) => scope_for_offset(db, &scopes, &source_map, node.with_value(offset)),
64         };
65         let resolver = resolver_for_scope(db.upcast(), def, scope);
66         SourceAnalyzer {
67             resolver,
68             body: Some(body),
69             body_source_map: Some(source_map),
70             infer: Some(db.infer(def)),
71             file_id,
72         }
73     }
74
75     pub(crate) fn new_for_body_no_infer(
76         db: &dyn HirDatabase,
77         def: DefWithBodyId,
78         node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
79         offset: Option<TextSize>,
80     ) -> SourceAnalyzer {
81         let (body, source_map) = db.body_with_source_map(def);
82         let scopes = db.expr_scopes(def);
83         let scope = match offset {
84             None => scope_for(&scopes, &source_map, node),
85             Some(offset) => scope_for_offset(db, &scopes, &source_map, node.with_value(offset)),
86         };
87         let resolver = resolver_for_scope(db.upcast(), def, scope);
88         SourceAnalyzer {
89             resolver,
90             body: Some(body),
91             body_source_map: Some(source_map),
92             infer: None,
93             file_id,
94         }
95     }
96
97     pub(crate) fn new_for_resolver(
98         resolver: Resolver,
99         node: InFile<&SyntaxNode>,
100     ) -> SourceAnalyzer {
101         SourceAnalyzer {
102             resolver,
103             body: None,
104             body_source_map: None,
105             infer: None,
106             file_id: node.file_id,
107         }
108     }
109
110     fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> {
111         let src = match expr {
112             ast::Expr::MacroCall(call) => {
113                 self.expand_expr(db, InFile::new(self.file_id, call.clone()))?
114             }
115             _ => InFile::new(self.file_id, expr.clone()),
116         };
117         let sm = self.body_source_map.as_ref()?;
118         sm.node_expr(src.as_ref())
119     }
120
121     fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> {
122         // FIXME: macros, see `expr_id`
123         let src = InFile { file_id: self.file_id, value: pat };
124         self.body_source_map.as_ref()?.node_pat(src)
125     }
126
127     fn expand_expr(
128         &self,
129         db: &dyn HirDatabase,
130         expr: InFile<ast::MacroCall>,
131     ) -> Option<InFile<ast::Expr>> {
132         let macro_file = self.body_source_map.as_ref()?.node_macro_file(expr.as_ref())?;
133         let expanded = db.parse_or_expand(macro_file)?;
134
135         let res = match ast::MacroCall::cast(expanded.clone()) {
136             Some(call) => self.expand_expr(db, InFile::new(macro_file, call))?,
137             _ => InFile::new(macro_file, ast::Expr::cast(expanded)?),
138         };
139         Some(res)
140     }
141
142     pub(crate) fn type_of_expr(
143         &self,
144         db: &dyn HirDatabase,
145         expr: &ast::Expr,
146     ) -> Option<(Type, Option<Type>)> {
147         let expr_id = self.expr_id(db, expr)?;
148         let infer = self.infer.as_ref()?;
149         let coerced = infer
150             .expr_adjustments
151             .get(&expr_id)
152             .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
153         let ty = infer[expr_id].clone();
154         let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
155         mk_ty(ty).zip(Some(coerced.and_then(mk_ty)))
156     }
157
158     pub(crate) fn type_of_pat(
159         &self,
160         db: &dyn HirDatabase,
161         pat: &ast::Pat,
162     ) -> Option<(Type, Option<Type>)> {
163         let pat_id = self.pat_id(pat)?;
164         let infer = self.infer.as_ref()?;
165         let coerced = infer
166             .pat_adjustments
167             .get(&pat_id)
168             .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
169         let ty = infer[pat_id].clone();
170         let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
171         mk_ty(ty).zip(Some(coerced.and_then(mk_ty)))
172     }
173
174     pub(crate) fn type_of_self(
175         &self,
176         db: &dyn HirDatabase,
177         param: &ast::SelfParam,
178     ) -> Option<Type> {
179         let src = InFile { file_id: self.file_id, value: param };
180         let pat_id = self.body_source_map.as_ref()?.node_self_param(src)?;
181         let ty = self.infer.as_ref()?[pat_id].clone();
182         Type::new_with_resolver(db, &self.resolver, ty)
183     }
184
185     pub(crate) fn resolve_method_call(
186         &self,
187         db: &dyn HirDatabase,
188         call: &ast::MethodCallExpr,
189     ) -> Option<(FunctionId, Substitution)> {
190         let expr_id = self.expr_id(db, &call.clone().into())?;
191         self.infer.as_ref()?.method_resolution(expr_id)
192     }
193
194     pub(crate) fn resolve_field(
195         &self,
196         db: &dyn HirDatabase,
197         field: &ast::FieldExpr,
198     ) -> Option<Field> {
199         let expr_id = self.expr_id(db, &field.clone().into())?;
200         self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into())
201     }
202
203     pub(crate) fn resolve_record_field(
204         &self,
205         db: &dyn HirDatabase,
206         field: &ast::RecordExprField,
207     ) -> Option<(Field, Option<Local>, Type)> {
208         let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
209         let expr = ast::Expr::from(record_expr);
210         let expr_id = self.body_source_map.as_ref()?.node_expr(InFile::new(self.file_id, &expr))?;
211
212         let local_name = field.field_name()?.as_name();
213         let local = if field.name_ref().is_some() {
214             None
215         } else {
216             let path = ModPath::from_segments(PathKind::Plain, once(local_name.clone()));
217             match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) {
218                 Some(ValueNs::LocalBinding(pat_id)) => {
219                     Some(Local { pat_id, parent: self.resolver.body_owner()? })
220                 }
221                 _ => None,
222             }
223         };
224         let (_, subst) = self.infer.as_ref()?.type_of_expr.get(expr_id)?.as_adt()?;
225         let variant = self.infer.as_ref()?.variant_resolution_for_expr(expr_id)?;
226         let variant_data = variant.variant_data(db.upcast());
227         let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
228         let field_ty =
229             db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
230         Some((field.into(), local, Type::new_with_resolver(db, &self.resolver, field_ty)?))
231     }
232
233     pub(crate) fn resolve_record_pat_field(
234         &self,
235         db: &dyn HirDatabase,
236         field: &ast::RecordPatField,
237     ) -> Option<Field> {
238         let field_name = field.field_name()?.as_name();
239         let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
240         let pat_id = self.pat_id(&record_pat.into())?;
241         let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id)?;
242         let variant_data = variant.variant_data(db.upcast());
243         let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
244         Some(field.into())
245     }
246
247     pub(crate) fn resolve_macro_call(
248         &self,
249         db: &dyn HirDatabase,
250         macro_call: InFile<&ast::MacroCall>,
251     ) -> Option<MacroDef> {
252         let ctx = body::LowerCtx::new(db.upcast(), macro_call.file_id);
253         let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?;
254         self.resolver.resolve_path_as_macro(db.upcast(), path.mod_path()).map(|it| it.into())
255     }
256
257     pub(crate) fn resolve_bind_pat_to_const(
258         &self,
259         db: &dyn HirDatabase,
260         pat: &ast::IdentPat,
261     ) -> Option<ModuleDef> {
262         let pat_id = self.pat_id(&pat.clone().into())?;
263         let body = self.body.as_ref()?;
264         let path = match &body[pat_id] {
265             Pat::Path(path) => path,
266             _ => return None,
267         };
268         let res = resolve_hir_path(db, &self.resolver, path)?;
269         match res {
270             PathResolution::Def(def) => Some(def),
271             _ => None,
272         }
273     }
274
275     pub(crate) fn resolve_path(
276         &self,
277         db: &dyn HirDatabase,
278         path: &ast::Path,
279     ) -> Option<PathResolution> {
280         let parent = path.syntax().parent();
281         let parent = || parent.clone();
282
283         let mut prefer_value_ns = false;
284         if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) {
285             let expr_id = self.expr_id(db, &path_expr.into())?;
286             let infer = self.infer.as_ref()?;
287             if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) {
288                 return Some(PathResolution::AssocItem(assoc.into()));
289             }
290             if let Some(VariantId::EnumVariantId(variant)) =
291                 infer.variant_resolution_for_expr(expr_id)
292             {
293                 return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
294             }
295             prefer_value_ns = true;
296         } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
297             let pat_id = self.pat_id(&path_pat.into())?;
298             if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
299                 return Some(PathResolution::AssocItem(assoc.into()));
300             }
301             if let Some(VariantId::EnumVariantId(variant)) =
302                 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
303             {
304                 return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
305             }
306         } else if let Some(rec_lit) = parent().and_then(ast::RecordExpr::cast) {
307             let expr_id = self.expr_id(db, &rec_lit.into())?;
308             if let Some(VariantId::EnumVariantId(variant)) =
309                 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
310             {
311                 return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
312             }
313         }
314
315         let record_pat = parent().and_then(ast::RecordPat::cast).map(ast::Pat::from);
316         let tuple_struct_pat = || parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from);
317         if let Some(pat) = record_pat.or_else(tuple_struct_pat) {
318             let pat_id = self.pat_id(&pat)?;
319             let variant_res_for_pat = self.infer.as_ref()?.variant_resolution_for_pat(pat_id);
320             if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat {
321                 return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
322             }
323         }
324
325         // This must be a normal source file rather than macro file.
326         let hygiene = Hygiene::new(db.upcast(), self.file_id);
327         let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene);
328         let hir_path = Path::from_src(path.clone(), &ctx)?;
329
330         // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
331         // trying to resolve foo::bar.
332         if let Some(use_tree) = parent().and_then(ast::UseTree::cast) {
333             if use_tree.coloncolon_token().is_some() {
334                 return resolve_hir_path_qualifier(db, &self.resolver, &hir_path);
335             }
336         }
337
338         let is_path_of_attr = path
339             .syntax()
340             .ancestors()
341             .map(|it| it.kind())
342             .take_while(|&kind| ast::Path::can_cast(kind) || ast::Meta::can_cast(kind))
343             .last()
344             .map_or(false, ast::Meta::can_cast);
345
346         // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are
347         // trying to resolve foo::bar.
348         if path.parent_path().is_some() {
349             return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path) {
350                 None if is_path_of_attr => {
351                     path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| {
352                         match self.resolver.krate() {
353                             Some(krate) => ToolModule::by_name(db, krate.into(), &name_ref.text()),
354                             None => ToolModule::builtin(&name_ref.text()),
355                         }
356                         .map(PathResolution::ToolModule)
357                     })
358                 }
359                 res => res,
360             };
361         } else if is_path_of_attr {
362             // Case where we are resolving the final path segment of a path in an attribute
363             // in this case we have to check for inert/builtin attributes and tools and prioritize
364             // resolution of attributes over other namespaces
365             let name_ref = path.as_single_name_ref();
366             let builtin = name_ref.as_ref().and_then(|name_ref| match self.resolver.krate() {
367                 Some(krate) => BuiltinAttr::by_name(db, krate.into(), &name_ref.text()),
368                 None => BuiltinAttr::builtin(&name_ref.text()),
369             });
370             if let builtin @ Some(_) = builtin {
371                 return builtin.map(PathResolution::BuiltinAttr);
372             }
373             return match resolve_hir_path_as_macro(db, &self.resolver, &hir_path) {
374                 res @ Some(m) if m.is_attr() => res.map(PathResolution::Macro),
375                 // this labels any path that starts with a tool module as the tool itself, this is technically wrong
376                 // but there is no benefit in differentiating these two cases for the time being
377                 _ => path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| {
378                     match self.resolver.krate() {
379                         Some(krate) => ToolModule::by_name(db, krate.into(), &name_ref.text()),
380                         None => ToolModule::builtin(&name_ref.text()),
381                     }
382                     .map(PathResolution::ToolModule)
383                 }),
384             };
385         }
386         if parent().map_or(false, |it| ast::Visibility::can_cast(it.kind())) {
387             resolve_hir_path_qualifier(db, &self.resolver, &hir_path)
388         } else {
389             resolve_hir_path_(db, &self.resolver, &hir_path, prefer_value_ns)
390         }
391     }
392
393     pub(crate) fn record_literal_missing_fields(
394         &self,
395         db: &dyn HirDatabase,
396         literal: &ast::RecordExpr,
397     ) -> Option<Vec<(Field, Type)>> {
398         let krate = self.resolver.krate()?;
399         let body = self.body.as_ref()?;
400         let infer = self.infer.as_ref()?;
401
402         let expr_id = self.expr_id(db, &literal.clone().into())?;
403         let substs = infer.type_of_expr[expr_id].as_adt()?.1;
404
405         let (variant, missing_fields, _exhaustive) =
406             record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?;
407         let res = self.missing_fields(db, krate, substs, variant, missing_fields);
408         Some(res)
409     }
410
411     pub(crate) fn record_pattern_missing_fields(
412         &self,
413         db: &dyn HirDatabase,
414         pattern: &ast::RecordPat,
415     ) -> Option<Vec<(Field, Type)>> {
416         let krate = self.resolver.krate()?;
417         let body = self.body.as_ref()?;
418         let infer = self.infer.as_ref()?;
419
420         let pat_id = self.pat_id(&pattern.clone().into())?;
421         let substs = infer.type_of_pat[pat_id].as_adt()?.1;
422
423         let (variant, missing_fields, _exhaustive) =
424             record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
425         let res = self.missing_fields(db, krate, substs, variant, missing_fields);
426         Some(res)
427     }
428
429     fn missing_fields(
430         &self,
431         db: &dyn HirDatabase,
432         krate: CrateId,
433         substs: &Substitution,
434         variant: VariantId,
435         missing_fields: Vec<LocalFieldId>,
436     ) -> Vec<(Field, Type)> {
437         let field_types = db.field_types(variant);
438
439         missing_fields
440             .into_iter()
441             .map(|local_id| {
442                 let field = FieldId { parent: variant, local_id };
443                 let ty = field_types[local_id].clone().substitute(Interner, substs);
444                 (field.into(), Type::new_with_resolver_inner(db, krate, &self.resolver, ty))
445             })
446             .collect()
447     }
448
449     pub(crate) fn expand(
450         &self,
451         db: &dyn HirDatabase,
452         macro_call: InFile<&ast::MacroCall>,
453     ) -> Option<HirFileId> {
454         let krate = self.resolver.krate()?;
455         let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
456             self.resolver.resolve_path_as_macro(db.upcast(), &path)
457         })?;
458         Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64)
459     }
460
461     pub(crate) fn resolve_variant(
462         &self,
463         db: &dyn HirDatabase,
464         record_lit: ast::RecordExpr,
465     ) -> Option<VariantId> {
466         let infer = self.infer.as_ref()?;
467         let expr_id = self.expr_id(db, &record_lit.into())?;
468         infer.variant_resolution_for_expr(expr_id)
469     }
470 }
471
472 fn scope_for(
473     scopes: &ExprScopes,
474     source_map: &BodySourceMap,
475     node: InFile<&SyntaxNode>,
476 ) -> Option<ScopeId> {
477     node.value
478         .ancestors()
479         .filter_map(ast::Expr::cast)
480         .filter_map(|it| source_map.node_expr(InFile::new(node.file_id, &it)))
481         .find_map(|it| scopes.scope_for(it))
482 }
483
484 fn scope_for_offset(
485     db: &dyn HirDatabase,
486     scopes: &ExprScopes,
487     source_map: &BodySourceMap,
488     offset: InFile<TextSize>,
489 ) -> Option<ScopeId> {
490     scopes
491         .scope_by_expr()
492         .iter()
493         .filter_map(|(id, scope)| {
494             let InFile { file_id, value } = source_map.expr_syntax(*id).ok()?;
495             if offset.file_id == file_id {
496                 let root = db.parse_or_expand(file_id)?;
497                 let node = value.to_node(&root);
498                 return Some((node.syntax().text_range(), scope));
499             }
500
501             // FIXME handle attribute expansion
502             let source = iter::successors(file_id.call_node(db.upcast()), |it| {
503                 it.file_id.call_node(db.upcast())
504             })
505             .find(|it| it.file_id == offset.file_id)
506             .filter(|it| it.value.kind() == SyntaxKind::MACRO_CALL)?;
507             Some((source.value.text_range(), scope))
508         })
509         // find containing scope
510         .min_by_key(|(expr_range, _scope)| {
511             (
512                 !(expr_range.start() <= offset.value && offset.value <= expr_range.end()),
513                 expr_range.len(),
514             )
515         })
516         .map(|(expr_range, scope)| {
517             adjust(db, scopes, source_map, expr_range, offset).unwrap_or(*scope)
518         })
519 }
520
521 // XXX: during completion, cursor might be outside of any particular
522 // expression. Try to figure out the correct scope...
523 fn adjust(
524     db: &dyn HirDatabase,
525     scopes: &ExprScopes,
526     source_map: &BodySourceMap,
527     expr_range: TextRange,
528     offset: InFile<TextSize>,
529 ) -> Option<ScopeId> {
530     let child_scopes = scopes
531         .scope_by_expr()
532         .iter()
533         .filter_map(|(id, scope)| {
534             let source = source_map.expr_syntax(*id).ok()?;
535             // FIXME: correctly handle macro expansion
536             if source.file_id != offset.file_id {
537                 return None;
538             }
539             let root = source.file_syntax(db.upcast());
540             let node = source.value.to_node(&root);
541             Some((node.syntax().text_range(), scope))
542         })
543         .filter(|&(range, _)| {
544             range.start() <= offset.value && expr_range.contains_range(range) && range != expr_range
545         });
546
547     child_scopes
548         .max_by(|&(r1, _), &(r2, _)| {
549             if r1.contains_range(r2) {
550                 std::cmp::Ordering::Greater
551             } else if r2.contains_range(r1) {
552                 std::cmp::Ordering::Less
553             } else {
554                 r1.start().cmp(&r2.start())
555             }
556         })
557         .map(|(_ptr, scope)| *scope)
558 }
559
560 #[inline]
561 pub(crate) fn resolve_hir_path(
562     db: &dyn HirDatabase,
563     resolver: &Resolver,
564     path: &Path,
565 ) -> Option<PathResolution> {
566     resolve_hir_path_(db, resolver, path, false)
567 }
568
569 #[inline]
570 pub(crate) fn resolve_hir_path_as_macro(
571     db: &dyn HirDatabase,
572     resolver: &Resolver,
573     path: &Path,
574 ) -> Option<MacroDef> {
575     resolver.resolve_path_as_macro(db.upcast(), path.mod_path()).map(Into::into)
576 }
577
578 fn resolve_hir_path_(
579     db: &dyn HirDatabase,
580     resolver: &Resolver,
581     path: &Path,
582     prefer_value_ns: bool,
583 ) -> Option<PathResolution> {
584     let types = || {
585         let (ty, unresolved) = match path.type_anchor() {
586             Some(type_ref) => {
587                 let (_, res) = TyLoweringContext::new(db, resolver).lower_ty_ext(type_ref);
588                 res.map(|ty_ns| (ty_ns, path.segments().first()))
589             }
590             None => {
591                 let (ty, remaining) =
592                     resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?;
593                 match remaining {
594                     Some(remaining) if remaining > 1 => None,
595                     _ => Some((ty, path.segments().get(1))),
596                 }
597             }
598         }?;
599
600         // If we are in a TypeNs for a Trait, and we have an unresolved name, try to resolve it as a type
601         // within the trait's associated types.
602         if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) {
603             if let Some(type_alias_id) =
604                 db.trait_data(trait_id).associated_type_by_name(&unresolved.name)
605             {
606                 return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
607             }
608         }
609
610         let res = match ty {
611             TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
612             TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
613             TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
614                 PathResolution::Def(Adt::from(it).into())
615             }
616             TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
617             TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
618             TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
619             TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
620         };
621         match unresolved {
622             Some(unresolved) => res
623                 .assoc_type_shorthand_candidates(db, |name, alias| {
624                     (name == unresolved.name).then(|| alias)
625                 })
626                 .map(TypeAlias::from)
627                 .map(Into::into)
628                 .map(PathResolution::Def),
629             None => Some(res),
630         }
631     };
632
633     let body_owner = resolver.body_owner();
634     let values = || {
635         resolver.resolve_path_in_value_ns_fully(db.upcast(), path.mod_path()).and_then(|val| {
636             let res = match val {
637                 ValueNs::LocalBinding(pat_id) => {
638                     let var = Local { parent: body_owner?, pat_id };
639                     PathResolution::Local(var)
640                 }
641                 ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()),
642                 ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()),
643                 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
644                 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
645                 ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
646                 ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
647                 ValueNs::GenericParam(it) => PathResolution::ConstParam(it.into()),
648             };
649             Some(res)
650         })
651     };
652
653     let items = || {
654         resolver
655             .resolve_module_path_in_items(db.upcast(), path.mod_path())
656             .take_types()
657             .map(|it| PathResolution::Def(it.into()))
658     };
659
660     let macros = || {
661         resolver
662             .resolve_path_as_macro(db.upcast(), path.mod_path())
663             .map(|def| PathResolution::Macro(def.into()))
664     };
665
666     if prefer_value_ns { values().or_else(types) } else { types().or_else(values) }
667         .or_else(items)
668         .or_else(macros)
669 }
670
671 /// Resolves a path where we know it is a qualifier of another path.
672 ///
673 /// For example, if we have:
674 /// ```
675 /// mod my {
676 ///     pub mod foo {
677 ///         struct Bar;
678 ///     }
679 ///
680 ///     pub fn foo() {}
681 /// }
682 /// ```
683 /// then we know that `foo` in `my::foo::Bar` refers to the module, not the function.
684 fn resolve_hir_path_qualifier(
685     db: &dyn HirDatabase,
686     resolver: &Resolver,
687     path: &Path,
688 ) -> Option<PathResolution> {
689     let items = resolver
690         .resolve_module_path_in_items(db.upcast(), path.mod_path())
691         .take_types()
692         .map(|it| PathResolution::Def(it.into()));
693
694     if items.is_some() {
695         return items;
696     }
697
698     resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty {
699         TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
700         TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
701         TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => PathResolution::Def(Adt::from(it).into()),
702         TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
703         TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
704         TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
705         TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
706     })
707 }