Skip to main content

hir/
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".
8use std::{
9    cell::OnceCell,
10    iter::{self, once},
11};
12
13use either::Either;
14use hir_def::{
15    AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, ExpressionStoreOwnerId, FieldId,
16    FunctionId, GenericDefId, LocalFieldId, ModuleDefId, StructId, VariantId,
17    expr_store::{
18        Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, HygieneId,
19        lower::ExprCollector,
20        path::Path,
21        scope::{ExprScopes, ScopeId},
22    },
23    hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId, generics::GenericParams},
24    lang_item::LangItems,
25    nameres::MacroSubNs,
26    resolver::{Resolver, TypeNs, ValueNs, resolver_for_scope},
27    type_ref::{Mutability, TypeRef, TypeRefId},
28};
29use hir_expand::{
30    HirFileId, InFile,
31    mod_path::{ModPath, PathKind, path},
32    name::{AsName, Name},
33};
34use hir_ty::{
35    Adjustment, InferBodyId, InferenceResult, LifetimeElisionKind, ParamEnvAndCrate,
36    TyLoweringContext,
37    diagnostics::{
38        InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields,
39        unsafe_operations,
40    },
41    lang_items::lang_items_for_bin_op,
42    method_resolution::{self, CandidateId},
43    next_solver::{
44        AliasTy, DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, Ty, TyKind, TypingMode,
45        infer::DbInternerInferExt,
46    },
47    traits::structurally_normalize_ty,
48};
49use intern::sym;
50use itertools::Itertools;
51use rustc_hash::FxHashSet;
52use rustc_type_ir::{
53    AliasTyKind,
54    inherent::{IntoKind, Ty as _},
55};
56use smallvec::SmallVec;
57use stdx::never;
58use syntax::{
59    SyntaxKind, SyntaxNode, TextRange, TextSize,
60    ast::{self, AstNode, RangeItem, RangeOp},
61};
62
63use crate::{
64    Adt, AnyFunctionId, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const,
65    DeriveHelper, EnumVariant, Field, Function, GenericSubstitution, Local, Macro, ModuleDef,
66    SemanticsImpl, Static, Struct, ToolModule, Trait, TupleField, Type, TypeAlias,
67    db::HirDatabase,
68    semantics::{PathResolution, PathResolutionPerNs},
69};
70
71/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
72/// original source files. It should not be used inside the HIR itself.
73#[derive(Debug)]
74pub(crate) struct SourceAnalyzer<'db> {
75    pub(crate) file_id: HirFileId,
76    pub(crate) resolver: Resolver<'db>,
77    pub(crate) body_or_sig: Option<BodyOrSig<'db>>,
78    pub(crate) infer_body: Option<InferBodyId>,
79}
80
81#[derive(Debug)]
82pub(crate) enum BodyOrSig<'db> {
83    Body {
84        def: DefWithBodyId,
85        body: &'db Body,
86        source_map: &'db BodySourceMap,
87        infer: Option<&'db InferenceResult>,
88    },
89    VariantFields {
90        def: VariantId,
91        store: &'db ExpressionStore,
92        source_map: &'db ExpressionStoreSourceMap,
93        infer: Option<&'db InferenceResult>,
94    },
95    Sig {
96        def: GenericDefId,
97        store: &'db ExpressionStore,
98        source_map: &'db ExpressionStoreSourceMap,
99        infer: Option<&'db InferenceResult>,
100        #[expect(dead_code)]
101        generics: &'db GenericParams,
102    },
103}
104
105impl<'db> SourceAnalyzer<'db> {
106    pub(crate) fn new_for_body(
107        db: &'db dyn HirDatabase,
108        def: DefWithBodyId,
109        node: InFile<&SyntaxNode>,
110        offset: Option<TextSize>,
111    ) -> SourceAnalyzer<'db> {
112        Self::new_for_body_(db, def, node, offset, Some(InferenceResult::of(db, def)))
113    }
114
115    pub(crate) fn new_for_body_no_infer(
116        db: &'db dyn HirDatabase,
117        def: DefWithBodyId,
118        node: InFile<&SyntaxNode>,
119        offset: Option<TextSize>,
120    ) -> SourceAnalyzer<'db> {
121        Self::new_for_body_(db, def, node, offset, None)
122    }
123
124    pub(crate) fn new_for_body_(
125        db: &'db dyn HirDatabase,
126        def: DefWithBodyId,
127        node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
128        offset: Option<TextSize>,
129        infer: Option<&'db InferenceResult>,
130    ) -> SourceAnalyzer<'db> {
131        let (body, source_map) = Body::with_source_map(db, def);
132        let scopes = ExprScopes::of(db, def);
133        let scope = match offset {
134            None => scope_for(db, scopes, source_map, node),
135            Some(offset) => {
136                debug_assert!(
137                    node.text_range().contains_inclusive(offset),
138                    "{:?} not in {:?}",
139                    offset,
140                    node.text_range()
141                );
142                scope_for_offset(db, scopes, source_map, node.file_id, offset)
143            }
144        };
145        let (scope, _expr) = scope.unzip();
146        let resolver = resolver_for_scope(db, def, scope);
147        SourceAnalyzer {
148            resolver,
149            body_or_sig: Some(BodyOrSig::Body { def, body, source_map, infer }),
150            file_id,
151            infer_body: Some(def.into()),
152        }
153    }
154
155    pub(crate) fn new_generic_def(
156        db: &'db dyn HirDatabase,
157        sema: &SemanticsImpl<'db>,
158        def: GenericDefId,
159        node: InFile<&SyntaxNode>,
160        offset: Option<TextSize>,
161    ) -> SourceAnalyzer<'db> {
162        Self::new_generic_def_(db, sema, def, node, offset, true)
163    }
164
165    pub(crate) fn new_generic_def_no_infer(
166        db: &'db dyn HirDatabase,
167        sema: &SemanticsImpl<'db>,
168        def: GenericDefId,
169        node: InFile<&SyntaxNode>,
170        offset: Option<TextSize>,
171    ) -> SourceAnalyzer<'db> {
172        Self::new_generic_def_(db, sema, def, node, offset, false)
173    }
174
175    pub(crate) fn new_generic_def_(
176        db: &'db dyn HirDatabase,
177        sema: &SemanticsImpl<'db>,
178        def: GenericDefId,
179        node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
180        offset: Option<TextSize>,
181        infer: bool,
182    ) -> SourceAnalyzer<'db> {
183        let (generics, store, source_map) = GenericParams::with_source_map(db, def);
184        let scopes = ExprScopes::of(db, def);
185        let scope = match offset {
186            None => scope_for(db, scopes, source_map, node),
187            Some(offset) => {
188                debug_assert!(
189                    node.text_range().contains_inclusive(offset),
190                    "{:?} not in {:?}",
191                    offset,
192                    node.text_range()
193                );
194                scope_for_offset(db, scopes, source_map, node.file_id, offset)
195            }
196        };
197        let (scope, expr) = scope.unzip();
198        let resolver = resolver_for_scope(db, def, scope);
199        let infer_body = expr.and_then(|expr| {
200            sema.infer_body_for_expr_or_pat(
201                ExpressionStoreOwnerId::Signature(def),
202                store,
203                expr.into(),
204            )
205        });
206        let infer = if infer && let Some(infer_body) = infer_body {
207            Some(InferenceResult::of(db, infer_body))
208        } else {
209            None
210        };
211        SourceAnalyzer {
212            resolver,
213            body_or_sig: Some(BodyOrSig::Sig { def, store, source_map, generics, infer }),
214            file_id,
215            infer_body,
216        }
217    }
218
219    pub(crate) fn new_variant_body(
220        db: &'db dyn HirDatabase,
221        sema: &SemanticsImpl<'db>,
222        def: VariantId,
223        node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
224        offset: Option<TextSize>,
225        infer: bool,
226    ) -> SourceAnalyzer<'db> {
227        let (fields, source_map) = def.fields_with_source_map(db);
228        let scopes = ExprScopes::of(db, def);
229        let scope = match offset {
230            None => scope_for(db, scopes, source_map, node),
231            Some(offset) => {
232                debug_assert!(
233                    node.text_range().contains_inclusive(offset),
234                    "{:?} not in {:?}",
235                    offset,
236                    node.text_range()
237                );
238                scope_for_offset(db, scopes, source_map, node.file_id, offset)
239            }
240        };
241        let (scope, expr) = scope.unzip();
242        let resolver = resolver_for_scope(db, def, scope);
243        let infer_body = expr.and_then(|expr| {
244            sema.infer_body_for_expr_or_pat(
245                ExpressionStoreOwnerId::VariantFields(def),
246                &fields.store,
247                expr.into(),
248            )
249        });
250        let infer = if infer && let Some(infer_body) = infer_body {
251            Some(InferenceResult::of(db, infer_body))
252        } else {
253            None
254        };
255        SourceAnalyzer {
256            resolver,
257            body_or_sig: Some(BodyOrSig::VariantFields {
258                def,
259                store: &fields.store,
260                source_map,
261                infer,
262            }),
263            file_id,
264            infer_body,
265        }
266    }
267
268    pub(crate) fn new_for_resolver(
269        resolver: Resolver<'db>,
270        node: InFile<&SyntaxNode>,
271    ) -> SourceAnalyzer<'db> {
272        SourceAnalyzer { resolver, body_or_sig: None, file_id: node.file_id, infer_body: None }
273    }
274
275    fn owner(&self) -> Option<ExpressionStoreOwnerId> {
276        self.body_or_sig.as_ref().map(|it| match *it {
277            BodyOrSig::VariantFields { def, .. } => def.into(),
278            BodyOrSig::Sig { def, .. } => def.into(),
279            BodyOrSig::Body { def, .. } => def.into(),
280        })
281    }
282
283    fn infer(&self) -> Option<&InferenceResult> {
284        self.body_or_sig.as_ref().and_then(|it| match it {
285            BodyOrSig::VariantFields { infer, .. }
286            | BodyOrSig::Sig { infer, .. }
287            | BodyOrSig::Body { infer, .. } => infer.as_deref(),
288        })
289    }
290
291    pub(crate) fn def(
292        &self,
293    ) -> Option<(
294        ExpressionStoreOwnerId,
295        &ExpressionStore,
296        &ExpressionStoreSourceMap,
297        Option<&InferenceResult>,
298    )> {
299        self.body_or_sig.as_ref().map(|it| match *it {
300            BodyOrSig::VariantFields { def, store, source_map, infer, .. } => {
301                (def.into(), store, source_map, infer)
302            }
303            BodyOrSig::Sig { def, store, source_map, infer, .. } => {
304                (def.into(), store, source_map, infer)
305            }
306            BodyOrSig::Body { def, body, source_map, infer, .. } => {
307                (def.into(), &body.store, &source_map.store, infer)
308            }
309        })
310    }
311
312    pub(crate) fn store(&self) -> Option<&ExpressionStore> {
313        self.body_or_sig.as_ref().map(|it| match it {
314            BodyOrSig::Sig { store, .. } => &**store,
315            BodyOrSig::VariantFields { store, .. } => &**store,
316            BodyOrSig::Body { body, .. } => &body.store,
317        })
318    }
319
320    pub(crate) fn store_sm(&self) -> Option<&ExpressionStoreSourceMap> {
321        self.body_or_sig.as_ref().map(|it| match it {
322            BodyOrSig::Sig { source_map, .. } => &**source_map,
323            BodyOrSig::VariantFields { source_map, .. } => &**source_map,
324            BodyOrSig::Body { source_map, .. } => &source_map.store,
325        })
326    }
327
328    fn param_and<'a>(&self, param_env: ParamEnv<'a>) -> ParamEnvAndCrate<'a> {
329        ParamEnvAndCrate { param_env, krate: self.resolver.krate() }
330    }
331
332    fn trait_environment(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> {
333        self.param_and(self.body_or_sig.as_ref().map_or_else(ParamEnv::empty, |body_or_sig| {
334            match *body_or_sig {
335                BodyOrSig::Body { def, .. } => db.trait_environment(def.into()),
336                BodyOrSig::VariantFields { def, .. } => db.trait_environment(def.into()),
337                BodyOrSig::Sig { def, .. } => db.trait_environment(def.into()),
338            }
339        }))
340    }
341
342    pub(crate) fn expr_id(&self, expr: ast::Expr) -> Option<ExprOrPatId> {
343        let src = InFile { file_id: self.file_id, value: expr };
344        self.store_sm()?.node_expr(src.as_ref())
345    }
346
347    fn pat_id(&self, pat: &ast::Pat) -> Option<ExprOrPatId> {
348        let src = InFile { file_id: self.file_id, value: pat };
349        self.store_sm()?.node_pat(src)
350    }
351
352    fn type_id(&self, pat: &ast::Type) -> Option<TypeRefId> {
353        let src = InFile { file_id: self.file_id, value: pat };
354        self.store_sm()?.node_type(src)
355    }
356
357    fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingId> {
358        let pat_id = self.pat_id(&pat.clone().into())?;
359        if let Pat::Bind { id, .. } = self.store()?[pat_id.as_pat()?] { Some(id) } else { None }
360    }
361
362    pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment]> {
363        // It is safe to omit destructuring assignments here because they have no adjustments (neither
364        // expressions nor patterns).
365        let expr_id = self.expr_id(expr.clone())?.as_expr()?;
366        let infer = self.infer()?;
367        infer.expr_adjustment(expr_id)
368    }
369
370    pub(crate) fn type_of_type(
371        &self,
372        db: &'db dyn HirDatabase,
373        ty: &ast::Type,
374    ) -> Option<Type<'db>> {
375        let interner = DbInterner::new_no_crate(db);
376
377        let type_ref = self.type_id(ty)?;
378
379        let generic_def = self.resolver.generic_def()?;
380        let generics = OnceCell::new();
381        let mut ty = TyLoweringContext::new(
382            db,
383            &self.resolver,
384            self.store()?,
385            generic_def.into(),
386            generic_def,
387            &generics,
388            // FIXME: Is this correct here? Anyway that should impact mostly diagnostics, which we don't emit here
389            // (this can impact the lifetimes generated, e.g. in `const` they won't be `'static`, but this seems like a
390            // small problem).
391            LifetimeElisionKind::Infer,
392        )
393        .lower_ty(type_ref);
394
395        // Try and substitute unknown types using InferenceResult
396        if let Some(infer) = self.infer()
397            && let Some(store) = self.store()
398        {
399            let mut inferred_types = vec![];
400            TypeRef::walk(type_ref, store, &mut |type_ref_id, type_ref| {
401                if matches!(type_ref, TypeRef::Placeholder) {
402                    inferred_types.push(infer.type_of_type_placeholder(type_ref_id));
403                }
404            });
405            let mut inferred_types = inferred_types.into_iter();
406
407            let substituted_ty = hir_ty::next_solver::fold::fold_tys(interner, ty, |ty| {
408                if ty.is_ty_error() { inferred_types.next().flatten().unwrap_or(ty) } else { ty }
409            });
410
411            // Only used the result if the placeholder and unknown type counts matched
412            let success =
413                inferred_types.next().is_none() && !substituted_ty.references_non_lt_error();
414            if success {
415                ty = substituted_ty;
416            }
417        }
418
419        Some(Type::new_with_resolver(db, &self.resolver, ty))
420    }
421
422    pub(crate) fn type_of_expr(
423        &self,
424        db: &'db dyn HirDatabase,
425        expr: &ast::Expr,
426    ) -> Option<(Type<'db>, Option<Type<'db>>)> {
427        let expr_id = self.expr_id(expr.clone())?;
428        let infer = self.infer()?;
429        let coerced = expr_id
430            .as_expr()
431            .and_then(|expr_id| infer.expr_adjustment(expr_id))
432            .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.as_ref()));
433        let ty = infer.expr_or_pat_ty(expr_id);
434        let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty);
435        Some((mk_ty(ty), coerced.map(mk_ty)))
436    }
437
438    pub(crate) fn type_of_pat(
439        &self,
440        db: &'db dyn HirDatabase,
441        pat: &ast::Pat,
442    ) -> Option<(Type<'db>, Option<Type<'db>>)> {
443        let expr_or_pat_id = self.pat_id(pat)?;
444        let infer = self.infer()?;
445        let coerced = match expr_or_pat_id {
446            ExprOrPatId::ExprId(idx) => infer
447                .expr_adjustment(idx)
448                .and_then(|adjusts| adjusts.last())
449                .map(|adjust| adjust.target.as_ref()),
450            ExprOrPatId::PatId(idx) => infer
451                .pat_adjustment(idx)
452                .and_then(|adjusts| adjusts.last())
453                .map(|adjust| adjust.source.as_ref()),
454        };
455
456        let ty = infer.expr_or_pat_ty(expr_or_pat_id);
457        let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty);
458        Some((mk_ty(ty), coerced.map(mk_ty)))
459    }
460
461    pub(crate) fn type_of_binding_in_pat(
462        &self,
463        db: &'db dyn HirDatabase,
464        pat: &ast::IdentPat,
465    ) -> Option<Type<'db>> {
466        let binding_id = self.binding_id_of_pat(pat)?;
467        let infer = self.infer()?;
468        let ty = infer.binding_ty(binding_id);
469        let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty);
470        Some(mk_ty(ty))
471    }
472
473    pub(crate) fn type_of_self(
474        &self,
475        db: &'db dyn HirDatabase,
476        _param: &ast::SelfParam,
477    ) -> Option<Type<'db>> {
478        let binding = match self.body_or_sig.as_ref()? {
479            BodyOrSig::Sig { .. } | BodyOrSig::VariantFields { .. } => return None,
480            BodyOrSig::Body { body, .. } => body.self_param()?,
481        };
482        let ty = self.infer()?.binding_ty(binding);
483        Some(Type::new_with_resolver(db, &self.resolver, ty))
484    }
485
486    pub(crate) fn binding_mode_of_pat(
487        &self,
488        _db: &'db dyn HirDatabase,
489        pat: &ast::IdentPat,
490    ) -> Option<BindingMode> {
491        let id = self.pat_id(&pat.clone().into())?;
492        let infer = self.infer()?;
493        Some(match infer.binding_mode(id.as_pat()?)? {
494            hir_ty::BindingMode(hir_ty::ByRef::No, _) => BindingMode::Move,
495            hir_ty::BindingMode(hir_ty::ByRef::Yes(hir_ty::next_solver::Mutability::Mut), _) => {
496                BindingMode::Ref(Mutability::Mut)
497            }
498            hir_ty::BindingMode(hir_ty::ByRef::Yes(hir_ty::next_solver::Mutability::Not), _) => {
499                BindingMode::Ref(Mutability::Shared)
500            }
501        })
502    }
503    pub(crate) fn pattern_adjustments(
504        &self,
505        db: &'db dyn HirDatabase,
506        pat: &ast::Pat,
507    ) -> Option<SmallVec<[Type<'db>; 1]>> {
508        let pat_id = self.pat_id(pat)?;
509        let infer = self.infer()?;
510        Some(
511            infer
512                .pat_adjustment(pat_id.as_pat()?)?
513                .iter()
514                .map(|adjust| Type::new_with_resolver(db, &self.resolver, adjust.source.as_ref()))
515                .collect(),
516        )
517    }
518
519    pub(crate) fn resolve_method_call_as_callable(
520        &self,
521        db: &'db dyn HirDatabase,
522        call: &ast::MethodCallExpr,
523    ) -> Option<Callable<'db>> {
524        let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
525        let (func, args) = self.infer()?.method_resolution(expr_id)?;
526        let interner = DbInterner::new_no_crate(db);
527        let ty = db.value_ty(func.into())?.instantiate(interner, args).skip_norm_wip();
528        let ty = Type::new_with_resolver(db, &self.resolver, ty);
529        let mut res = ty.as_callable(db)?;
530        res.is_bound_method = true;
531        Some(res)
532    }
533
534    pub(crate) fn resolve_method_call(
535        &self,
536        db: &'db dyn HirDatabase,
537        call: &ast::MethodCallExpr,
538    ) -> Option<Function> {
539        let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
540        let (f_in_trait, substs) = self.infer()?.method_resolution(expr_id)?;
541
542        Some(self.resolve_impl_method_or_trait_def(db, f_in_trait, substs))
543    }
544
545    pub(crate) fn resolve_method_call_fallback(
546        &self,
547        db: &'db dyn HirDatabase,
548        call: &ast::MethodCallExpr,
549    ) -> Option<(Either<Function, Field>, Option<GenericSubstitution<'db>>)> {
550        let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
551        let inference_result = self.infer()?;
552        match inference_result.method_resolution(expr_id) {
553            Some((f_in_trait, substs)) => {
554                let (fn_, subst) =
555                    self.resolve_impl_method_or_trait_def_with_subst(db, f_in_trait, substs);
556                Some((
557                    Either::Left(fn_),
558                    GenericSubstitution::new_from_fn(fn_, subst, self.trait_environment(db)),
559                ))
560            }
561            None => {
562                inference_result.field_resolution(expr_id).and_then(Either::left).map(|field| {
563                    (Either::Right(field.into()), self.field_subst(expr_id, inference_result, db))
564                })
565            }
566        }
567    }
568
569    pub(crate) fn resolve_expr_as_callable(
570        &self,
571        db: &'db dyn HirDatabase,
572        call: &ast::Expr,
573    ) -> Option<Callable<'db>> {
574        let (orig, adjusted) = self.type_of_expr(db, &call.clone())?;
575        adjusted.unwrap_or(orig).as_callable(db)
576    }
577
578    pub(crate) fn resolve_field(
579        &self,
580        field: &ast::FieldExpr,
581    ) -> Option<Either<Field, TupleField>> {
582        let def = self.infer_body?;
583        let expr_id = self.expr_id(field.clone().into())?.as_expr()?;
584        self.infer()?.field_resolution(expr_id).map(|it| {
585            it.map_either(Into::into, |f| TupleField { owner: def, tuple: f.tuple, index: f.index })
586        })
587    }
588
589    fn field_subst(
590        &self,
591        field_expr: ExprId,
592        infer: &InferenceResult,
593        db: &'db dyn HirDatabase,
594    ) -> Option<GenericSubstitution<'db>> {
595        let body = self.store()?;
596        if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] {
597            let (adt, subst) = infer.type_of_expr_with_adjust(object_expr)?.as_adt()?;
598            return Some(GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)));
599        }
600        None
601    }
602
603    pub(crate) fn resolve_field_fallback(
604        &self,
605        db: &'db dyn HirDatabase,
606        field: &ast::FieldExpr,
607    ) -> Option<(Either<Either<Field, TupleField>, Function>, Option<GenericSubstitution<'db>>)>
608    {
609        let def = self.infer_body?;
610        let expr_id = self.expr_id(field.clone().into())?.as_expr()?;
611        let inference_result = self.infer()?;
612        match inference_result.field_resolution(expr_id) {
613            Some(field) => match field {
614                Either::Left(field) => Some((
615                    Either::Left(Either::Left(field.into())),
616                    self.field_subst(expr_id, inference_result, db),
617                )),
618                Either::Right(field) => Some((
619                    Either::Left(Either::Right(TupleField {
620                        owner: def,
621                        tuple: field.tuple,
622                        index: field.index,
623                    })),
624                    None,
625                )),
626            },
627            None => inference_result.method_resolution(expr_id).map(|(f, substs)| {
628                let (f, subst) = self.resolve_impl_method_or_trait_def_with_subst(db, f, substs);
629                (
630                    Either::Right(f),
631                    GenericSubstitution::new_from_fn(f, subst, self.trait_environment(db)),
632                )
633            }),
634        }
635    }
636
637    pub(crate) fn resolve_range_pat(
638        &self,
639        db: &'db dyn HirDatabase,
640        range_pat: &ast::RangePat,
641    ) -> Option<StructId> {
642        self.resolve_range_struct(
643            db,
644            range_pat.op_kind()?,
645            range_pat.start().is_some(),
646            range_pat.end().is_some(),
647        )
648    }
649
650    pub(crate) fn resolve_range_expr(
651        &self,
652        db: &'db dyn HirDatabase,
653        range_expr: &ast::RangeExpr,
654    ) -> Option<StructId> {
655        self.resolve_range_struct(
656            db,
657            range_expr.op_kind()?,
658            range_expr.start().is_some(),
659            range_expr.end().is_some(),
660        )
661    }
662
663    fn resolve_range_struct(
664        &self,
665        db: &'db dyn HirDatabase,
666        op_kind: RangeOp,
667        has_start: bool,
668        has_end: bool,
669    ) -> Option<StructId> {
670        let has_new_range = self.resolver.top_level_def_map().features().new_range;
671        let lang_items = self.lang_items(db);
672        match (op_kind, has_start, has_end) {
673            (RangeOp::Exclusive, false, false) => lang_items.RangeFull,
674            (RangeOp::Exclusive, false, true) => lang_items.RangeTo,
675            (RangeOp::Exclusive, true, false) => {
676                if has_new_range {
677                    lang_items.RangeFromCopy
678                } else {
679                    lang_items.RangeFrom
680                }
681            }
682            (RangeOp::Exclusive, true, true) => {
683                if has_new_range {
684                    lang_items.RangeCopy
685                } else {
686                    lang_items.Range
687                }
688            }
689            (RangeOp::Inclusive, false, true) => {
690                if has_new_range {
691                    lang_items.RangeToInclusiveCopy
692                } else {
693                    lang_items.RangeToInclusive
694                }
695            }
696            (RangeOp::Inclusive, true, true) => {
697                if has_new_range {
698                    lang_items.RangeInclusiveCopy
699                } else {
700                    lang_items.RangeInclusiveStruct
701                }
702            }
703            // [E0586] inclusive ranges must be bounded at the end
704            (RangeOp::Inclusive, false, false) => None,
705            (RangeOp::Inclusive, true, false) => None,
706        }
707    }
708
709    pub(crate) fn resolve_await_to_poll(
710        &self,
711        db: &'db dyn HirDatabase,
712        await_expr: &ast::AwaitExpr,
713    ) -> Option<Function> {
714        let mut ty = self.ty_of_expr(await_expr.expr()?)?;
715
716        let into_future_trait = self
717            .resolver
718            .resolve_known_trait(db, &path![core::future::IntoFuture])
719            .map(Trait::from);
720
721        if let Some(into_future_trait) = into_future_trait {
722            let type_ = Type::new_with_resolver(db, &self.resolver, ty);
723            if type_.impls_trait(db, into_future_trait, &[]) {
724                let items = into_future_trait.items(db);
725                let into_future_type = items.into_iter().find_map(|item| match item {
726                    AssocItem::TypeAlias(alias)
727                        if alias.name(db) == Name::new_symbol_root(sym::IntoFuture) =>
728                    {
729                        Some(alias)
730                    }
731                    _ => None,
732                })?;
733                let future_trait = type_.normalize_trait_assoc_type(db, &[], into_future_type)?;
734                ty = future_trait.ty;
735            }
736        }
737
738        let poll_fn = self.lang_items(db).FuturePoll?;
739        // HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself
740        // doesn't have any generic parameters, so we skip building another subst for `poll()`.
741        let substs = GenericArgs::new_from_slice(&[ty.into()]);
742        Some(self.resolve_impl_method_or_trait_def(db, poll_fn, substs))
743    }
744
745    pub(crate) fn resolve_prefix_expr(
746        &self,
747        db: &'db dyn HirDatabase,
748        prefix_expr: &ast::PrefixExpr,
749    ) -> Option<Function> {
750        let lang_items = self.lang_items(db);
751        let (_op_trait, op_fn) = match prefix_expr.op_kind()? {
752            ast::UnaryOp::Deref => {
753                // This can be either `Deref::deref` or `DerefMut::deref_mut`.
754                // Since deref kind is inferenced and stored in `InferenceResult.method_resolution`,
755                // use that result to find out which one it is.
756                let (deref_trait, deref) = (lang_items.Deref?, lang_items.Deref_deref?);
757                self.infer()
758                    .and_then(|infer| {
759                        let expr = self.expr_id(prefix_expr.clone().into())?.as_expr()?;
760                        let (func, _) = infer.method_resolution(expr)?;
761                        let (deref_mut_trait, deref_mut) =
762                            (lang_items.DerefMut?, lang_items.DerefMut_deref_mut?);
763                        if func == deref_mut { Some((deref_mut_trait, deref_mut)) } else { None }
764                    })
765                    .unwrap_or((deref_trait, deref))
766            }
767            ast::UnaryOp::Not => (lang_items.Not?, lang_items.Not_not?),
768            ast::UnaryOp::Neg => (lang_items.Neg?, lang_items.Neg_neg?),
769        };
770
771        let ty = self.ty_of_expr(prefix_expr.expr()?)?;
772
773        // HACK: subst for all methods coincides with that for their trait because the methods
774        // don't have any generic parameters, so we skip building another subst for the methods.
775        let substs = GenericArgs::new_from_slice(&[ty.into()]);
776
777        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
778    }
779
780    pub(crate) fn resolve_index_expr(
781        &self,
782        db: &'db dyn HirDatabase,
783        index_expr: &ast::IndexExpr,
784    ) -> Option<Function> {
785        let base_ty = self.ty_of_expr(index_expr.base()?)?;
786        let index_ty = self.ty_of_expr(index_expr.index()?)?;
787        let lang_items = self.lang_items(db);
788
789        let (_index_trait, index_fn) = (lang_items.Index?, lang_items.Index_index?);
790        let op_fn = self
791            .infer()
792            .and_then(|infer| {
793                let expr = self.expr_id(index_expr.clone().into())?.as_expr()?;
794                let (func, _) = infer.method_resolution(expr)?;
795                let (_index_mut_trait, index_mut_fn) =
796                    (lang_items.IndexMut_index_mut?, lang_items.IndexMut_index_mut?);
797                if func == index_mut_fn { Some(index_mut_fn) } else { None }
798            })
799            .unwrap_or(index_fn);
800        // HACK: subst for all methods coincides with that for their trait because the methods
801        // don't have any generic parameters, so we skip building another subst for the methods.
802        let substs = GenericArgs::new_from_slice(&[base_ty.into(), index_ty.into()]);
803        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
804    }
805
806    pub(crate) fn resolve_bin_expr(
807        &self,
808        db: &'db dyn HirDatabase,
809        binop_expr: &ast::BinExpr,
810    ) -> Option<Function> {
811        let op = binop_expr.op_kind()?;
812        let lhs = self.ty_of_expr(binop_expr.lhs()?)?;
813        let rhs = self.ty_of_expr(binop_expr.rhs()?)?;
814
815        let (op_fn, _op_trait) = lang_items_for_bin_op(self.lang_items(db), op)
816            .and_then(|(method, trait_)| method.zip(trait_))?;
817        // HACK: subst for `index()` coincides with that for `Index` because `index()` itself
818        // doesn't have any generic parameters, so we skip building another subst for `index()`.
819        let substs = GenericArgs::new_from_slice(&[lhs.into(), rhs.into()]);
820
821        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
822    }
823
824    pub(crate) fn resolve_try_expr(
825        &self,
826        db: &'db dyn HirDatabase,
827        try_expr: &ast::TryExpr,
828    ) -> Option<Function> {
829        let ty = self.ty_of_expr(try_expr.expr()?)?;
830
831        let op_fn = self.lang_items(db).TryTraitBranch?;
832        // HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself
833        // doesn't have any generic parameters, so we skip building another subst for `branch()`.
834        let substs = GenericArgs::new_from_slice(&[ty.into()]);
835
836        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
837    }
838
839    pub(crate) fn resolve_record_field(
840        &self,
841        db: &'db dyn HirDatabase,
842        field: &ast::RecordExprField,
843    ) -> Option<(Field, Option<Local>, Type<'db>, GenericSubstitution<'db>)> {
844        let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
845        let expr = ast::Expr::from(record_expr);
846        let expr_id = self.store_sm()?.node_expr(InFile::new(self.file_id, &expr))?;
847        let interner = DbInterner::new_no_crate(db);
848
849        let ast_name = field.field_name()?;
850        let local_name = ast_name.as_name();
851        let local = if field.name_ref().is_some() {
852            None
853        } else {
854            // Shorthand syntax, resolve to the local
855            let path = Path::from_known_path_with_no_generic(ModPath::from_segments(
856                PathKind::Plain,
857                once(local_name.clone()),
858            ));
859            match self.resolver.resolve_path_in_value_ns_fully(
860                db,
861                &path,
862                name_hygiene(db, InFile::new(self.file_id, ast_name.syntax())),
863            ) {
864                Some(ValueNs::LocalBinding(binding_id)) => Some(Local {
865                    binding_id,
866                    parent: self.owner()?,
867                    parent_infer: self.infer_body?,
868                }),
869                _ => None,
870            }
871        };
872        let (adt, subst) = self.infer()?.type_of_expr_or_pat(expr_id)?.as_adt()?;
873        let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?;
874        let variant_data = variant.fields(db);
875        let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
876        let field_ty = (*db.field_types(variant).get(field.local_id)?)
877            .get()
878            .instantiate(interner, subst)
879            .skip_norm_wip();
880        Some((
881            field.into(),
882            local,
883            Type::new_with_resolver(db, &self.resolver, field_ty),
884            GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)),
885        ))
886    }
887
888    pub(crate) fn resolve_record_pat_field(
889        &self,
890        db: &'db dyn HirDatabase,
891        field: &ast::RecordPatField,
892    ) -> Option<(Field, Type<'db>, GenericSubstitution<'db>)> {
893        let interner = DbInterner::new_no_crate(db);
894        let field_name = field.field_name()?.as_name();
895        let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
896        let pat_id = self.pat_id(&record_pat.into())?;
897        let variant = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?;
898        let variant_data = variant.fields(db);
899        let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
900        let (adt, subst) = self.infer()?.pat_ty(pat_id.as_pat()?).as_adt()?;
901        let field_ty = (*db.field_types(variant).get(field.local_id)?)
902            .get()
903            .instantiate(interner, subst)
904            .skip_norm_wip();
905        Some((
906            field.into(),
907            Type::new_with_resolver(db, &self.resolver, field_ty),
908            GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)),
909        ))
910    }
911
912    pub(crate) fn resolve_bind_pat_to_const(
913        &self,
914        db: &'db dyn HirDatabase,
915        pat: &ast::IdentPat,
916    ) -> Option<ModuleDef> {
917        let expr_or_pat_id = self.pat_id(&pat.clone().into())?;
918        let store = self.store()?;
919
920        let path = match expr_or_pat_id {
921            ExprOrPatId::ExprId(idx) => match &store[idx] {
922                Expr::Path(path) => path,
923                _ => return None,
924            },
925            ExprOrPatId::PatId(idx) => match &store[idx] {
926                Pat::Path(path) => path,
927                _ => return None,
928            },
929        };
930
931        let store_owner = self.resolver.expression_store_owner();
932        let res = resolve_hir_value_path(
933            db,
934            &self.resolver,
935            store_owner,
936            self.infer_body,
937            path,
938            HygieneId::ROOT,
939        )?;
940        match res {
941            PathResolution::Def(def) => Some(def),
942            _ => None,
943        }
944    }
945
946    pub(crate) fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option<crate::TypeParam> {
947        let name = name.as_name();
948        self.resolver
949            .all_generic_params()
950            .find_map(|(params, parent)| params.find_type_by_name(&name, parent))
951            .map(crate::TypeParam::from)
952    }
953
954    pub(crate) fn resolve_offset_of_field(
955        &self,
956        db: &'db dyn HirDatabase,
957        name_ref: &ast::NameRef,
958    ) -> Option<(Either<crate::EnumVariant, crate::Field>, GenericSubstitution<'db>)> {
959        let offset_of_expr = ast::OffsetOfExpr::cast(name_ref.syntax().parent()?)?;
960        let container = offset_of_expr.ty()?;
961        let container = self.type_of_type(db, &container)?;
962
963        let trait_env = container.env;
964
965        let interner = DbInterner::new_with(db, trait_env.krate);
966        let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
967
968        let mut container = Either::Right(container.ty);
969        for field_name in offset_of_expr.fields() {
970            if let Either::Right(container) = &mut container {
971                *container = structurally_normalize_ty(&infcx, *container, trait_env.param_env);
972            }
973            let handle_variants =
974                |variant: VariantId, subst: GenericArgs<'db>, container: &mut _| {
975                    let fields = variant.fields(db);
976                    let field = fields.field(&field_name.as_name())?;
977                    let field_types = db.field_types(variant);
978                    *container = Either::Right(
979                        field_types[field].get().instantiate(interner, subst).skip_norm_wip(),
980                    );
981                    let generic_def = match variant {
982                        VariantId::EnumVariantId(it) => it.loc(db).parent.into(),
983                        VariantId::StructId(it) => it.into(),
984                        VariantId::UnionId(it) => it.into(),
985                    };
986                    Some((
987                        Either::Right(Field { parent: variant.into(), id: field }),
988                        generic_def,
989                        subst,
990                    ))
991                };
992            let temp_ty = Ty::new_error(interner, ErrorGuaranteed);
993            let (field_def, generic_def, subst) =
994                match std::mem::replace(&mut container, Either::Right(temp_ty)) {
995                    Either::Left((variant_id, subst)) => {
996                        handle_variants(VariantId::from(variant_id), subst, &mut container)?
997                    }
998                    Either::Right(container_ty) => match container_ty.kind() {
999                        TyKind::Adt(adt_def, subst) => match adt_def.def_id() {
1000                            AdtId::StructId(id) => {
1001                                handle_variants(id.into(), subst, &mut container)?
1002                            }
1003                            AdtId::UnionId(id) => {
1004                                handle_variants(id.into(), subst, &mut container)?
1005                            }
1006                            AdtId::EnumId(id) => {
1007                                let variants = id.enum_variants(db);
1008                                let variant = variants.variant(&field_name.as_name())?;
1009                                container = Either::Left((variant, subst));
1010                                (Either::Left(EnumVariant { id: variant }), id.into(), subst)
1011                            }
1012                        },
1013                        _ => return None,
1014                    },
1015                };
1016
1017            if field_name.syntax().text_range() == name_ref.syntax().text_range() {
1018                return Some((field_def, GenericSubstitution::new(generic_def, subst, trait_env)));
1019            }
1020        }
1021        never!("the `NameRef` is a child of the `OffsetOfExpr`, we should've visited it");
1022        None
1023    }
1024
1025    pub(crate) fn resolve_path(
1026        &self,
1027        db: &'db dyn HirDatabase,
1028        path: &ast::Path,
1029    ) -> Option<(PathResolution, Option<GenericSubstitution<'db>>)> {
1030        let parent = path.syntax().parent();
1031        let parent = || parent.clone();
1032
1033        let mut prefer_value_ns = false;
1034        let resolved = (|| {
1035            let infer = self.infer()?;
1036            if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) {
1037                let expr_id = self.expr_id(path_expr.into())?;
1038                if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_id) {
1039                    let (assoc, subst) = match assoc {
1040                        CandidateId::FunctionId(f_in_trait) => {
1041                            match infer.type_of_expr_or_pat(expr_id) {
1042                                None => {
1043                                    let subst = GenericSubstitution::new(
1044                                        f_in_trait.into(),
1045                                        subs,
1046                                        self.trait_environment(db),
1047                                    );
1048                                    (AssocItem::Function(f_in_trait.into()), Some(subst))
1049                                }
1050                                Some(func_ty) => {
1051                                    if let TyKind::FnDef(_fn_def, subs) = func_ty.kind() {
1052                                        let (fn_, subst) = self
1053                                            .resolve_impl_method_or_trait_def_with_subst(
1054                                                db, f_in_trait, subs,
1055                                            );
1056                                        let subst = GenericSubstitution::new_from_fn(
1057                                            fn_,
1058                                            subst,
1059                                            self.trait_environment(db),
1060                                        );
1061                                        (AssocItem::Function(fn_), subst)
1062                                    } else {
1063                                        let subst = GenericSubstitution::new(
1064                                            f_in_trait.into(),
1065                                            subs,
1066                                            self.trait_environment(db),
1067                                        );
1068                                        (AssocItem::Function(f_in_trait.into()), Some(subst))
1069                                    }
1070                                }
1071                            }
1072                        }
1073                        CandidateId::ConstId(const_id) => {
1074                            let (konst, subst) =
1075                                self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);
1076                            let subst = GenericSubstitution::new(
1077                                konst.into(),
1078                                subst,
1079                                self.trait_environment(db),
1080                            );
1081                            (AssocItem::Const(konst.into()), Some(subst))
1082                        }
1083                    };
1084
1085                    return Some((PathResolution::Def(assoc.into()), subst));
1086                }
1087                if let Some(VariantId::EnumVariantId(variant)) =
1088                    infer.variant_resolution_for_expr_or_pat(expr_id)
1089                {
1090                    return Some((
1091                        PathResolution::Def(ModuleDef::EnumVariant(variant.into())),
1092                        None,
1093                    ));
1094                }
1095                prefer_value_ns = true;
1096            } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
1097                let expr_or_pat_id = self.pat_id(&path_pat.into())?;
1098                if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_or_pat_id)
1099                {
1100                    let (assoc, subst) = match assoc {
1101                        CandidateId::ConstId(const_id) => {
1102                            let (konst, subst) =
1103                                self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);
1104                            let subst = GenericSubstitution::new(
1105                                konst.into(),
1106                                subst,
1107                                self.trait_environment(db),
1108                            );
1109                            (AssocItemId::from(konst), subst)
1110                        }
1111                        CandidateId::FunctionId(function_id) => (
1112                            function_id.into(),
1113                            GenericSubstitution::new(
1114                                function_id.into(),
1115                                subs,
1116                                self.trait_environment(db),
1117                            ),
1118                        ),
1119                    };
1120                    return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst)));
1121                }
1122                if let Some(VariantId::EnumVariantId(variant)) =
1123                    infer.variant_resolution_for_expr_or_pat(expr_or_pat_id)
1124                {
1125                    return Some((
1126                        PathResolution::Def(ModuleDef::EnumVariant(variant.into())),
1127                        None,
1128                    ));
1129                }
1130            } else if let Some(rec_lit) = parent().and_then(ast::RecordExpr::cast) {
1131                let expr_id = self.expr_id(rec_lit.into())?;
1132                if let Some(VariantId::EnumVariantId(variant)) =
1133                    infer.variant_resolution_for_expr_or_pat(expr_id)
1134                {
1135                    return Some((
1136                        PathResolution::Def(ModuleDef::EnumVariant(variant.into())),
1137                        None,
1138                    ));
1139                }
1140            } else {
1141                let record_pat = parent().and_then(ast::RecordPat::cast).map(ast::Pat::from);
1142                let tuple_struct_pat =
1143                    || parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from);
1144                if let Some(pat) = record_pat.or_else(tuple_struct_pat) {
1145                    let pat_id = self.pat_id(&pat)?;
1146                    let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id.as_pat()?);
1147                    if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat {
1148                        return Some((
1149                            PathResolution::Def(ModuleDef::EnumVariant(variant.into())),
1150                            None,
1151                        ));
1152                    }
1153                }
1154            }
1155            None
1156        })();
1157        if resolved.is_some() {
1158            return resolved;
1159        }
1160
1161        // FIXME: collectiong here shouldnt be necessary?
1162        let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
1163        let hir_path =
1164            collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;
1165        let parent_hir_path = path
1166            .parent_path()
1167            .and_then(|p| collector.lower_path(p, &mut ExprCollector::impl_trait_error_allocator));
1168        let (store, _) = collector.store.finish();
1169
1170        // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
1171        // trying to resolve foo::bar.
1172        if let Some(use_tree) = parent().and_then(ast::UseTree::cast)
1173            && use_tree.coloncolon_token().is_some()
1174        {
1175            return resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store)
1176                .map(|it| (it, None));
1177        }
1178
1179        let meta_path = path
1180            .syntax()
1181            .ancestors()
1182            .take_while(|it| {
1183                let kind = it.kind();
1184                ast::Path::can_cast(kind) || ast::Meta::can_cast(kind)
1185            })
1186            .last()
1187            .and_then(ast::Meta::cast);
1188
1189        // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are
1190        // trying to resolve foo::bar.
1191        if let Some(parent_hir_path) = parent_hir_path {
1192            return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store) {
1193                None if meta_path.is_some() => path
1194                    .first_segment()
1195                    .and_then(|it| it.name_ref())
1196                    .and_then(|name_ref| {
1197                        ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
1198                            .map(PathResolution::ToolModule)
1199                    })
1200                    .map(|it| (it, None)),
1201                // Case the type name conflict with use module,
1202                // e.g.
1203                // ```
1204                // use std::str;
1205                // fn main() {
1206                //     str::from_utf8();  // as module std::str
1207                //     str::len();        // as primitive type str
1208                //     str::no_exist_item(); // as primitive type str
1209                // }
1210                // ```
1211                Some(it) if matches!(it, PathResolution::Def(ModuleDef::BuiltinType(_))) => {
1212                    if let Some(mod_path) = hir_path.mod_path()
1213                        && let Some(ModuleDefId::ModuleId(id)) =
1214                            self.resolver.resolve_module_path_in_items(db, mod_path).take_types()
1215                    {
1216                        let parent_hir_name = parent_hir_path.segments().get(1).map(|it| it.name);
1217                        let module = crate::Module { id };
1218                        if module
1219                            .scope(db, None)
1220                            .into_iter()
1221                            .any(|(name, _)| Some(&name) == parent_hir_name)
1222                        {
1223                            return Some((PathResolution::Def(ModuleDef::Module(module)), None));
1224                        };
1225                    }
1226                    Some((it, None))
1227                }
1228                // FIXME: We do not show substitutions for parts of path, because this is really complex
1229                // due to the interactions with associated items of `impl`s and associated items of associated
1230                // types.
1231                res => res.map(|it| (it, None)),
1232            };
1233        } else if let Some(meta_path) = meta_path {
1234            // Case where we are resolving the final path segment of a path in an attribute
1235            // in this case we have to check for inert/builtin attributes and tools and prioritize
1236            // resolution of attributes over other namespaces
1237            if let Some(name_ref) = path.as_single_name_ref() {
1238                let builtin = BuiltinAttr::builtin(&name_ref.text());
1239                if builtin.is_some() {
1240                    return builtin.map(|it| (PathResolution::BuiltinAttr(it), None));
1241                }
1242
1243                if let Some(attr) = meta_path.parent_attr() {
1244                    let adt =
1245                        attr.syntax().ancestors().find_map(ast::Item::cast).and_then(
1246                            |it| match it {
1247                                ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
1248                                ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
1249                                ast::Item::Union(it) => Some(ast::Adt::Union(it)),
1250                                _ => None,
1251                            },
1252                        );
1253                    if let Some(adt) = adt {
1254                        let ast_id = db.ast_id_map(self.file_id).ast_id(&adt);
1255                        if let Some(helpers) = self
1256                            .resolver
1257                            .def_map()
1258                            .derive_helpers_in_scope(InFile::new(self.file_id, ast_id))
1259                        {
1260                            // FIXME: Multiple derives can have the same helper
1261                            let name_ref = name_ref.as_name();
1262                            for (macro_id, mut helpers) in
1263                                helpers.iter().chunk_by(|(_, macro_id, ..)| macro_id).into_iter()
1264                            {
1265                                if let Some(idx) = helpers.position(|(name, ..)| *name == name_ref)
1266                                {
1267                                    return Some((
1268                                        PathResolution::DeriveHelper(DeriveHelper {
1269                                            derive: *macro_id,
1270                                            idx: idx as u32,
1271                                        }),
1272                                        None,
1273                                    ));
1274                                }
1275                            }
1276                        }
1277                    }
1278                }
1279            }
1280            return match resolve_hir_path_as_attr_macro(db, &self.resolver, &hir_path) {
1281                Some(m) => Some((PathResolution::Def(ModuleDef::Macro(m)), None)),
1282                // this labels any path that starts with a tool module as the tool itself, this is technically wrong
1283                // but there is no benefit in differentiating these two cases for the time being
1284                None => path
1285                    .first_segment()
1286                    .and_then(|it| it.name_ref())
1287                    .and_then(|name_ref| {
1288                        ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
1289                            .map(PathResolution::ToolModule)
1290                    })
1291                    .map(|it| (it, None)),
1292            };
1293        }
1294        if parent().is_some_and(|it| ast::Visibility::can_cast(it.kind())) {
1295            // No substitution because only modules can be inside visibilities, and those have no generics.
1296            resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store).map(|it| (it, None))
1297        } else {
1298            // Probably a type, no need to show substitutions for those.
1299            let res = resolve_hir_path_(
1300                db,
1301                &self.resolver,
1302                self.infer_body,
1303                &hir_path,
1304                prefer_value_ns,
1305                name_hygiene(db, InFile::new(self.file_id, path.syntax())),
1306                Some(&store),
1307                false,
1308            )
1309            .any()?;
1310            let subst = (|| {
1311                let parent = parent()?;
1312                let ty = if let Some(expr) = ast::Expr::cast(parent.clone()) {
1313                    let expr_id = self.expr_id(expr)?;
1314                    self.infer()?.type_of_expr_or_pat(expr_id)?
1315                } else if let Some(pat) = ast::Pat::cast(parent) {
1316                    let pat_id = self.pat_id(&pat)?;
1317                    self.infer()?.expr_or_pat_ty(pat_id)
1318                } else {
1319                    return None;
1320                };
1321                let env = self.trait_environment(db);
1322                let (subst, expected_resolution) = match ty.kind() {
1323                    TyKind::Adt(adt_def, subst) => {
1324                        let adt_id = adt_def.def_id();
1325                        (
1326                            GenericSubstitution::new(adt_id.into(), subst, env),
1327                            PathResolution::Def(ModuleDef::Adt(adt_id.into())),
1328                        )
1329                    }
1330                    TyKind::Alias(AliasTy {
1331                        kind: AliasTyKind::Projection { def_id },
1332                        args,
1333                        ..
1334                    }) => {
1335                        let assoc_id = def_id.0;
1336                        (
1337                            GenericSubstitution::new(assoc_id.into(), args, env),
1338                            PathResolution::Def(ModuleDef::TypeAlias(assoc_id.into())),
1339                        )
1340                    }
1341                    TyKind::FnDef(fn_id, subst) => {
1342                        let generic_def_id = match fn_id.0 {
1343                            CallableDefId::StructId(id) => id.into(),
1344                            CallableDefId::FunctionId(id) => id.into(),
1345                            CallableDefId::EnumVariantId(_) => return None,
1346                        };
1347                        (
1348                            GenericSubstitution::new(generic_def_id, subst, env),
1349                            PathResolution::Def(ModuleDefId::from(fn_id.0).into()),
1350                        )
1351                    }
1352                    _ => return None,
1353                };
1354                if res != expected_resolution {
1355                    // The user will not understand where we're coming from. This can happen (I think) with type aliases.
1356                    return None;
1357                }
1358                Some(subst)
1359            })();
1360            Some((res, subst))
1361        }
1362    }
1363
1364    pub(crate) fn resolve_hir_path_per_ns(
1365        &self,
1366        db: &dyn HirDatabase,
1367        path: &ast::Path,
1368    ) -> Option<PathResolutionPerNs> {
1369        let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
1370        let hir_path =
1371            collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;
1372        let (store, _) = collector.store.finish();
1373        Some(resolve_hir_path_(
1374            db,
1375            &self.resolver,
1376            self.infer_body,
1377            &hir_path,
1378            false,
1379            name_hygiene(db, InFile::new(self.file_id, path.syntax())),
1380            Some(&store),
1381            true,
1382        ))
1383    }
1384
1385    pub(crate) fn record_literal_missing_fields(
1386        &self,
1387        db: &'db dyn HirDatabase,
1388        literal: &ast::RecordExpr,
1389    ) -> Option<Vec<(Field, Type<'db>)>> {
1390        let body = self.store()?;
1391        let infer = self.infer()?;
1392
1393        let expr_id = self.expr_id(literal.clone().into())?.as_expr()?;
1394        let substs = infer.expr_ty(expr_id).as_adt()?.1;
1395        let (variant, missing_fields) =
1396            record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?;
1397        let res = self.missing_fields(db, substs, variant, missing_fields);
1398        Some(res)
1399    }
1400
1401    pub(crate) fn record_literal_matched_fields(
1402        &self,
1403        db: &'db dyn HirDatabase,
1404        literal: &ast::RecordExpr,
1405    ) -> Option<Vec<(Field, Type<'db>)>> {
1406        let body = self.store()?;
1407        let infer = self.infer()?;
1408
1409        let expr_id = self.expr_id(literal.clone().into())?.as_expr()?;
1410        let substs = infer.expr_ty(expr_id).as_adt()?.1;
1411        let (variant, matched_fields) =
1412            record_literal_matched_fields(db, infer, expr_id, &body[expr_id])?;
1413
1414        let res = self.missing_fields(db, substs, variant, matched_fields);
1415        Some(res)
1416    }
1417
1418    pub(crate) fn record_pattern_missing_fields(
1419        &self,
1420        db: &'db dyn HirDatabase,
1421        pattern: &ast::RecordPat,
1422    ) -> Option<Vec<(Field, Type<'db>)>> {
1423        let body = self.store()?;
1424        let infer = self.infer()?;
1425
1426        let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;
1427        let substs = infer.pat_ty(pat_id).as_adt()?.1;
1428
1429        let (variant, missing_fields) =
1430            record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
1431        let res = self.missing_fields(db, substs, variant, missing_fields);
1432        Some(res)
1433    }
1434
1435    pub(crate) fn record_pattern_matched_fields(
1436        &self,
1437        db: &'db dyn HirDatabase,
1438        pattern: &ast::RecordPat,
1439    ) -> Option<Vec<(Field, Type<'db>)>> {
1440        let body = self.store()?;
1441        let infer = self.infer()?;
1442
1443        let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;
1444        let substs = infer.pat_ty(pat_id).as_adt()?.1;
1445
1446        let (variant, matched_fields) =
1447            record_pattern_matched_fields(db, infer, pat_id, &body[pat_id])?;
1448        let res = self.missing_fields(db, substs, variant, matched_fields);
1449        Some(res)
1450    }
1451
1452    fn missing_fields(
1453        &self,
1454        db: &'db dyn HirDatabase,
1455        substs: GenericArgs<'db>,
1456        variant: VariantId,
1457        missing_fields: Vec<LocalFieldId>,
1458    ) -> Vec<(Field, Type<'db>)> {
1459        let interner = DbInterner::new_no_crate(db);
1460        let field_types = db.field_types(variant);
1461
1462        missing_fields
1463            .into_iter()
1464            .map(|local_id| {
1465                let field = FieldId { parent: variant, local_id };
1466                let ty = field_types[local_id].get().instantiate(interner, substs).skip_norm_wip();
1467                (field.into(), Type::new_with_resolver_inner(db, &self.resolver, ty))
1468            })
1469            .collect()
1470    }
1471
1472    pub(crate) fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
1473        let infer = self.infer()?;
1474        let expr_id = self.expr_id(record_lit.into())?;
1475        infer.variant_resolution_for_expr_or_pat(expr_id)
1476    }
1477
1478    pub(crate) fn is_unsafe_macro_call_expr(
1479        &self,
1480        db: &'db dyn HirDatabase,
1481        macro_expr: InFile<&ast::MacroExpr>,
1482    ) -> bool {
1483        if let Some((def, body, sm, Some(infer))) = self.def()
1484            && let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr)
1485        {
1486            let mut is_unsafe = false;
1487            let mut walk_expr = |expr_id| {
1488                unsafe_operations(db, infer, def, body, expr_id, &mut |_, inside_unsafe_block| {
1489                    is_unsafe |= inside_unsafe_block == InsideUnsafeBlock::No
1490                })
1491            };
1492            match expanded_expr {
1493                ExprOrPatId::ExprId(expanded_expr) => walk_expr(expanded_expr),
1494                ExprOrPatId::PatId(expanded_pat) => body.walk_exprs_in_pat(expanded_pat, walk_expr),
1495            }
1496            return is_unsafe;
1497        }
1498        false
1499    }
1500
1501    /// Returns the range of the implicit template argument and its resolution at the given `offset`
1502    pub(crate) fn resolve_offset_in_format_args(
1503        &self,
1504        db: &'db dyn HirDatabase,
1505        format_args: InFile<&ast::FormatArgsExpr>,
1506        offset: TextSize,
1507    ) -> Option<(TextRange, Option<PathResolution>)> {
1508        let (hygiene, implicits) = self.store_sm()?.implicit_format_args(format_args)?;
1509        implicits.iter().find(|(range, _)| range.contains_inclusive(offset)).map(|(range, name)| {
1510            (
1511                *range,
1512                resolve_hir_value_path(
1513                    db,
1514                    &self.resolver,
1515                    self.resolver.expression_store_owner(),
1516                    self.infer_body,
1517                    &Path::from_known_path_with_no_generic(ModPath::from_segments(
1518                        PathKind::Plain,
1519                        Some(name.clone()),
1520                    )),
1521                    hygiene,
1522                ),
1523            )
1524        })
1525    }
1526
1527    pub(crate) fn resolve_offset_in_asm_template(
1528        &self,
1529        asm: InFile<&ast::AsmExpr>,
1530        line: usize,
1531        offset: TextSize,
1532    ) -> Option<(ExpressionStoreOwnerId, (ExprId, TextRange, usize))> {
1533        let (def, _, sm, _) = self.def()?;
1534        let (expr, args) = sm.asm_template_args(asm)?;
1535        Some(def).zip(
1536            args.get(line)?
1537                .iter()
1538                .find(|(range, _)| range.contains_inclusive(offset))
1539                .map(|(range, idx)| (expr, *range, *idx)),
1540        )
1541    }
1542
1543    pub(crate) fn as_format_args_parts<'a>(
1544        &'a self,
1545        db: &'a dyn HirDatabase,
1546        format_args: InFile<&ast::FormatArgsExpr>,
1547    ) -> Option<impl Iterator<Item = (TextRange, Option<PathResolution>)> + 'a> {
1548        let (hygiene, names) = self.store_sm()?.implicit_format_args(format_args)?;
1549        Some(names.iter().map(move |(range, name)| {
1550            (
1551                *range,
1552                resolve_hir_value_path(
1553                    db,
1554                    &self.resolver,
1555                    self.resolver.expression_store_owner(),
1556                    self.infer_body,
1557                    &Path::from_known_path_with_no_generic(ModPath::from_segments(
1558                        PathKind::Plain,
1559                        Some(name.clone()),
1560                    )),
1561                    hygiene,
1562                ),
1563            )
1564        }))
1565    }
1566
1567    pub(crate) fn as_asm_parts(
1568        &self,
1569        asm: InFile<&ast::AsmExpr>,
1570    ) -> Option<(ExpressionStoreOwnerId, (ExprId, &[Vec<(TextRange, usize)>]))> {
1571        let (def, _, sm, _) = self.def()?;
1572        Some(def).zip(sm.asm_template_args(asm))
1573    }
1574
1575    fn resolve_impl_method_or_trait_def(
1576        &self,
1577        db: &'db dyn HirDatabase,
1578        func: FunctionId,
1579        substs: GenericArgs<'db>,
1580    ) -> Function {
1581        self.resolve_impl_method_or_trait_def_with_subst(db, func, substs).0
1582    }
1583
1584    fn resolve_impl_method_or_trait_def_with_subst(
1585        &self,
1586        db: &'db dyn HirDatabase,
1587        func: FunctionId,
1588        substs: GenericArgs<'db>,
1589    ) -> (Function, GenericArgs<'db>) {
1590        let owner = match self.resolver.expression_store_owner() {
1591            Some(it) => it,
1592            None => return (func.into(), substs),
1593        };
1594        let env = self.param_and(db.trait_environment(owner));
1595        let (func, args) = db.lookup_impl_method(env, func, substs);
1596        match func {
1597            Either::Left(func) => (func.into(), args),
1598            Either::Right((impl_, method)) => {
1599                (Function { id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } }, args)
1600            }
1601        }
1602    }
1603
1604    fn resolve_impl_const_or_trait_def_with_subst(
1605        &self,
1606        db: &'db dyn HirDatabase,
1607        const_id: ConstId,
1608        subs: GenericArgs<'db>,
1609    ) -> (ConstId, GenericArgs<'db>) {
1610        let owner = match self.resolver.expression_store_owner() {
1611            Some(it) => it,
1612            None => return (const_id, subs),
1613        };
1614        let env = self.param_and(db.trait_environment(owner));
1615        let interner = DbInterner::new_with(db, env.krate);
1616        let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
1617        method_resolution::lookup_impl_const(&infcx, env.param_env, const_id, subs)
1618    }
1619
1620    fn lang_items<'a>(&self, db: &'a dyn HirDatabase) -> &'a LangItems {
1621        hir_def::lang_item::lang_items(db, self.resolver.krate())
1622    }
1623
1624    fn ty_of_expr(&self, expr: ast::Expr) -> Option<Ty<'db>> {
1625        self.infer()?.type_of_expr_or_pat(self.expr_id(expr)?)
1626    }
1627}
1628
1629// Note: the `ExprId` here does not need to be accurate, what's important is that it points at the same
1630// inference root.
1631fn scope_for(
1632    db: &dyn HirDatabase,
1633    scopes: &ExprScopes,
1634    source_map: &ExpressionStoreSourceMap,
1635    node: InFile<&SyntaxNode>,
1636) -> Option<(ScopeId, ExprId)> {
1637    node.ancestors_with_macros(db)
1638        .take_while(|it| {
1639            let kind = it.kind();
1640            !ast::Item::can_cast(kind)
1641                || ast::MacroCall::can_cast(kind)
1642                || ast::Use::can_cast(kind)
1643                || ast::AsmExpr::can_cast(kind)
1644        })
1645        .filter_map(|it| it.map(ast::Expr::cast).transpose())
1646        .filter_map(|it| source_map.node_expr(it.as_ref())?.as_expr())
1647        .find_map(|expr| scopes.scope_for(expr).map(|scope| (scope, expr)))
1648}
1649
1650fn scope_for_offset(
1651    db: &dyn HirDatabase,
1652    scopes: &ExprScopes,
1653    source_map: &ExpressionStoreSourceMap,
1654    from_file: HirFileId,
1655    offset: TextSize,
1656) -> Option<(ScopeId, ExprId)> {
1657    scopes
1658        .scope_by_expr()
1659        .iter()
1660        .filter_map(|(id, scope)| {
1661            let InFile { file_id, value } = source_map.expr_syntax(id).ok()?;
1662            if from_file == file_id {
1663                return Some((value.text_range(), scope, id));
1664            }
1665
1666            // FIXME handle attribute expansion
1667            let source = iter::successors(file_id.macro_file().map(|it| it.call_node(db)), |it| {
1668                Some(it.file_id.macro_file()?.call_node(db))
1669            })
1670            .find(|it| it.file_id == from_file)
1671            .filter(|it| it.kind() == SyntaxKind::MACRO_CALL)?;
1672            Some((source.text_range(), scope, id))
1673        })
1674        .filter(|(expr_range, _scope, _expr)| {
1675            expr_range.start() <= offset && offset <= expr_range.end()
1676        })
1677        // find containing scope
1678        .min_by_key(|(expr_range, _scope, _expr)| expr_range.len())
1679        .map(|(expr_range, scope, expr)| {
1680            adjust(db, scopes, source_map, expr_range, from_file, offset).unwrap_or((*scope, expr))
1681        })
1682}
1683
1684// XXX: during completion, cursor might be outside of any particular
1685// expression. Try to figure out the correct scope...
1686fn adjust(
1687    db: &dyn HirDatabase,
1688    scopes: &ExprScopes,
1689    source_map: &ExpressionStoreSourceMap,
1690    expr_range: TextRange,
1691    from_file: HirFileId,
1692    offset: TextSize,
1693) -> Option<(ScopeId, ExprId)> {
1694    let child_scopes = scopes
1695        .scope_by_expr()
1696        .iter()
1697        .filter_map(|(id, scope)| {
1698            let source = source_map.expr_syntax(id).ok()?;
1699            // FIXME: correctly handle macro expansion
1700            if source.file_id != from_file {
1701                return None;
1702            }
1703            let root = source.file_syntax(db);
1704            let node = source.value.to_node(&root);
1705            Some((node.syntax().text_range(), scope, id))
1706        })
1707        .filter(|&(range, _, _)| {
1708            range.start() <= offset && expr_range.contains_range(range) && range != expr_range
1709        });
1710
1711    child_scopes
1712        .max_by(|&(r1, _, _), &(r2, _, _)| {
1713            if r1.contains_range(r2) {
1714                std::cmp::Ordering::Greater
1715            } else if r2.contains_range(r1) {
1716                std::cmp::Ordering::Less
1717            } else {
1718                r1.start().cmp(&r2.start())
1719            }
1720        })
1721        .map(|(_ptr, scope, expr)| (*scope, expr))
1722}
1723
1724#[inline]
1725pub(crate) fn resolve_hir_path(
1726    db: &dyn HirDatabase,
1727    resolver: &Resolver<'_>,
1728    infer_body: Option<InferBodyId>,
1729    path: &Path,
1730    hygiene: HygieneId,
1731    store: Option<&ExpressionStore>,
1732) -> Option<PathResolution> {
1733    resolve_hir_path_(db, resolver, infer_body, path, false, hygiene, store, false).any()
1734}
1735
1736#[inline]
1737pub(crate) fn resolve_hir_path_as_attr_macro(
1738    db: &dyn HirDatabase,
1739    resolver: &Resolver<'_>,
1740    path: &Path,
1741) -> Option<Macro> {
1742    resolver
1743        .resolve_path_as_macro(db, path.mod_path()?, Some(MacroSubNs::Attr))
1744        .map(|(it, _)| it)
1745        .map(Into::into)
1746}
1747
1748fn resolve_hir_path_(
1749    db: &dyn HirDatabase,
1750    resolver: &Resolver<'_>,
1751    infer_body: Option<InferBodyId>,
1752    path: &Path,
1753    prefer_value_ns: bool,
1754    hygiene: HygieneId,
1755    store: Option<&ExpressionStore>,
1756    resolve_per_ns: bool,
1757) -> PathResolutionPerNs {
1758    let types = || {
1759        let (ty, unresolved) = match path.type_anchor() {
1760            Some(type_ref) => resolver.generic_def().and_then(|def| {
1761                let generics = OnceCell::new();
1762                let (_, res) = TyLoweringContext::new(
1763                    db,
1764                    resolver,
1765                    store?,
1766                    def.into(),
1767                    def,
1768                    &generics,
1769                    LifetimeElisionKind::Infer,
1770                )
1771                .lower_ty_ext(type_ref);
1772                res.map(|ty_ns| (ty_ns, path.segments().first()))
1773            }),
1774            None => {
1775                let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db, path)?;
1776                match remaining_idx {
1777                    Some(remaining_idx) => {
1778                        if remaining_idx + 1 == path.segments().len() {
1779                            Some((ty, path.segments().last()))
1780                        } else {
1781                            None
1782                        }
1783                    }
1784                    None => Some((ty, None)),
1785                }
1786            }
1787        }?;
1788
1789        // If we are in a TypeNs for a Trait, and we have an unresolved name, try to resolve it as a type
1790        // within the trait's associated types.
1791        if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty)
1792            && let Some(type_alias_id) =
1793                trait_id.trait_items(db).associated_type_by_name(unresolved.name)
1794        {
1795            return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
1796        }
1797
1798        let res = match ty {
1799            TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
1800            TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()),
1801            TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
1802                PathResolution::Def(Adt::from(it).into())
1803            }
1804            TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
1805            TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
1806            TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
1807            TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
1808            TypeNs::ModuleId(it) => PathResolution::Def(ModuleDef::Module(it.into())),
1809        };
1810        match unresolved {
1811            Some(unresolved) => resolver
1812                .generic_def()
1813                .and_then(|def| {
1814                    hir_ty::associated_type_shorthand_candidates(
1815                        db,
1816                        def,
1817                        res.in_type_ns()?,
1818                        |name, _| name == unresolved.name,
1819                    )
1820                })
1821                .map(TypeAlias::from)
1822                .map(Into::into)
1823                .map(PathResolution::Def),
1824            None => Some(res),
1825        }
1826    };
1827
1828    let body_owner = resolver.expression_store_owner();
1829    let values = || resolve_hir_value_path(db, resolver, body_owner, infer_body, path, hygiene);
1830
1831    let items = || {
1832        resolver
1833            .resolve_module_path_in_items(db, path.mod_path()?)
1834            .take_types()
1835            .map(|it| PathResolution::Def(it.into()))
1836    };
1837
1838    let macros = || {
1839        resolver
1840            .resolve_path_as_macro(db, path.mod_path()?, None)
1841            .map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into())))
1842    };
1843
1844    if resolve_per_ns {
1845        PathResolutionPerNs {
1846            type_ns: types().or_else(items),
1847            value_ns: values(),
1848            macro_ns: macros(),
1849        }
1850    } else {
1851        let res = if prefer_value_ns {
1852            values()
1853                .map(|value_ns| PathResolutionPerNs::new(None, Some(value_ns), None))
1854                .unwrap_or_else(|| PathResolutionPerNs::new(types(), None, None))
1855        } else {
1856            types()
1857                .map(|type_ns| PathResolutionPerNs::new(Some(type_ns), None, None))
1858                .unwrap_or_else(|| PathResolutionPerNs::new(None, values(), None))
1859        };
1860
1861        if res.any().is_some() {
1862            res
1863        } else if let Some(type_ns) = items() {
1864            PathResolutionPerNs::new(Some(type_ns), None, None)
1865        } else {
1866            PathResolutionPerNs::new(None, None, macros())
1867        }
1868    }
1869}
1870
1871fn resolve_hir_value_path(
1872    db: &dyn HirDatabase,
1873    resolver: &Resolver<'_>,
1874    store_owner: Option<ExpressionStoreOwnerId>,
1875    infer_body: Option<InferBodyId>,
1876    path: &Path,
1877    hygiene: HygieneId,
1878) -> Option<PathResolution> {
1879    resolver.resolve_path_in_value_ns_fully(db, path, hygiene).and_then(|val| {
1880        let res = match val {
1881            ValueNs::LocalBinding(binding_id) => {
1882                let var = Local { parent: store_owner?, parent_infer: infer_body?, binding_id };
1883                PathResolution::Local(var)
1884            }
1885            ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()),
1886            ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()),
1887            ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
1888            ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
1889            ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
1890            ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
1891            ValueNs::GenericParam(id) => PathResolution::ConstParam(id.into()),
1892        };
1893        Some(res)
1894    })
1895}
1896
1897/// Resolves a path where we know it is a qualifier of another path.
1898///
1899/// For example, if we have:
1900/// ```
1901/// mod my {
1902///     pub mod foo {
1903///         struct Bar;
1904///     }
1905///
1906///     pub fn foo() {}
1907/// }
1908/// ```
1909/// then we know that `foo` in `my::foo::Bar` refers to the module, not the function.
1910fn resolve_hir_path_qualifier(
1911    db: &dyn HirDatabase,
1912    resolver: &Resolver<'_>,
1913    path: &Path,
1914    store: &ExpressionStore,
1915) -> Option<PathResolution> {
1916    (|| {
1917        let (ty, unresolved) = match path.type_anchor() {
1918            Some(type_ref) => resolver.generic_def().and_then(|def| {
1919                let generics = OnceCell::new();
1920                let (_, res) = TyLoweringContext::new(
1921                    db,
1922                    resolver,
1923                    store,
1924                    def.into(),
1925                    def,
1926                    &generics,
1927                    LifetimeElisionKind::Infer,
1928                )
1929                .lower_ty_ext(type_ref);
1930                res.map(|ty_ns| (ty_ns, path.segments().first()))
1931            }),
1932            None => {
1933                let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db, path)?;
1934                match remaining_idx {
1935                    Some(remaining_idx) => {
1936                        if remaining_idx + 1 == path.segments().len() {
1937                            Some((ty, path.segments().last()))
1938                        } else {
1939                            None
1940                        }
1941                    }
1942                    None => Some((ty, None)),
1943                }
1944            }
1945        }?;
1946
1947        // If we are in a TypeNs for a Trait, and we have an unresolved name, try to resolve it as a type
1948        // within the trait's associated types.
1949        if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty)
1950            && let Some(type_alias_id) =
1951                trait_id.trait_items(db).associated_type_by_name(unresolved.name)
1952        {
1953            return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
1954        }
1955
1956        let res = match ty {
1957            TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
1958            TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()),
1959            TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
1960                PathResolution::Def(Adt::from(it).into())
1961            }
1962            TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
1963            TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
1964            TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
1965            TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
1966            TypeNs::ModuleId(it) => PathResolution::Def(ModuleDef::Module(it.into())),
1967        };
1968        match unresolved {
1969            Some(unresolved) => resolver
1970                .generic_def()
1971                .and_then(|def| {
1972                    hir_ty::associated_type_shorthand_candidates(
1973                        db,
1974                        def,
1975                        res.in_type_ns()?,
1976                        |name, _| name == unresolved.name,
1977                    )
1978                })
1979                .map(TypeAlias::from)
1980                .map(Into::into)
1981                .map(PathResolution::Def),
1982            None => Some(res),
1983        }
1984    })()
1985    .or_else(|| {
1986        resolver
1987            .resolve_module_path_in_items(db, path.mod_path()?)
1988            .take_types()
1989            .map(|it| PathResolution::Def(it.into()))
1990    })
1991}
1992
1993pub(crate) fn name_hygiene(db: &dyn HirDatabase, name: InFile<&SyntaxNode>) -> HygieneId {
1994    let Some(macro_file) = name.file_id.macro_file() else {
1995        return HygieneId::ROOT;
1996    };
1997    let span_map = db.expansion_span_map(macro_file);
1998    let ctx = span_map.span_at(name.value.text_range().start()).ctx;
1999    HygieneId::new(ctx.opaque_and_semiopaque(db))
2000}
2001
2002fn record_literal_matched_fields(
2003    db: &dyn HirDatabase,
2004    infer: &InferenceResult,
2005    id: ExprId,
2006    expr: &Expr,
2007) -> Option<(VariantId, Vec<LocalFieldId>)> {
2008    let (fields, _spread) = match expr {
2009        Expr::RecordLit { fields, spread, .. } => (fields, spread),
2010        _ => return None,
2011    };
2012
2013    let variant_def = infer.variant_resolution_for_expr(id)?;
2014    if let VariantId::UnionId(_) = variant_def {
2015        return None;
2016    }
2017
2018    let variant_data = variant_def.fields(db);
2019
2020    let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
2021    // suggest fields if:
2022    // - not in code
2023    let matched_fields: Vec<LocalFieldId> = variant_data
2024        .fields()
2025        .iter()
2026        .filter_map(|(f, d)| (!specified_fields.contains(&d.name)).then_some(f))
2027        .collect();
2028    if matched_fields.is_empty() {
2029        return None;
2030    }
2031    Some((variant_def, matched_fields))
2032}
2033
2034fn record_pattern_matched_fields(
2035    db: &dyn HirDatabase,
2036    infer: &InferenceResult,
2037    id: PatId,
2038    pat: &Pat,
2039) -> Option<(VariantId, Vec<LocalFieldId>)> {
2040    let (fields, _ellipsis) = match pat {
2041        Pat::Record { path: _, args, ellipsis } => (args, *ellipsis),
2042        _ => return None,
2043    };
2044
2045    let variant_def = infer.variant_resolution_for_pat(id)?;
2046    if let VariantId::UnionId(_) = variant_def {
2047        return None;
2048    }
2049
2050    let variant_data = variant_def.fields(db);
2051
2052    let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
2053    // suggest fields if:
2054    // - not in code
2055    let matched_fields: Vec<LocalFieldId> = variant_data
2056        .fields()
2057        .iter()
2058        .filter_map(|(f, d)| if !specified_fields.contains(&d.name) { Some(f) } else { None })
2059        .collect();
2060    if matched_fields.is_empty() {
2061        return None;
2062    }
2063    Some((variant_def, matched_fields))
2064}