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