src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs RUST 2,179 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,179.
1//! Lookup hir elements using positions in the source code. This is a lossy2//! transformation: in general, a single source might correspond to several3//! modules, functions, etc, due to macros, cfgs and `#[path=]` attributes on4//! modules.5//!6//! So, this modules should not be used during hir construction, it exists7//! purely for "IDE needs".8use std::{9    cell::OnceCell,10    iter::{self, once},11};1213use 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};6263use 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};7172/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of73/// 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}8283#[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}106107impl<'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    }116117    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    }125126    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    }157158    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    }167168    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    }177178    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            None213        };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    }222223    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            None258        };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    }272273    pub(crate) fn new_for_resolver(274        resolver: Resolver<'db>,275        node: InFile<&SyntaxNode>,276    ) -> SourceAnalyzer<'db> {277        SourceAnalyzer {278            type_owner: resolver279                .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    }288289    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    }296297    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    }304305    pub(crate) fn ty(&self, ty: Ty<'db>) -> Type<'db> {306        Type { owner: self.type_owner, ty: EarlyBinder::bind(ty) }307    }308309    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    }329330    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    }337338    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    }345346    fn param_and<'a>(&self, param_env: ParamEnv<'a>) -> ParamEnvAndCrate<'a> {347        ParamEnvAndCrate { param_env, krate: self.resolver.krate() }348    }349350    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    }367368    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            // FIXME375            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        }387388        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        }410411        PredicateEvaluationResult::holds("predicate holds")412    }413414    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    }418419    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    }423424    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    }428429    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    }433434    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 (neither436        // 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    }441442    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);448449        let type_ref = self.type_id(ty)?;450451        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 here462            // (this can impact the lifetimes generated, e.g. in `const` they won't be `'static`, but this seems like a463            // small problem).464            LifetimeElisionKind::Infer,465        )466        .with_infer_vars_behavior(Some(&mut vars_cts))467        .lower_ty(type_ref);468469        struct VarsCtx<'a, 'db> {470            types: &'db DefaultAny<'db>,471            infer: Option<&'a InferenceResult>,472        }473474        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) = span477                    && let Some(ty) =478                        self.infer.and_then(|infer| infer.type_of_type_placeholder(type_ref))479                {480                    ty481                } else {482                    self.types.types.error483                }484            }485            fn next_const_var(&mut self, _span: hir_ty::Span) -> hir_ty::next_solver::Const<'db> {486                self.types.consts.error487            }488            fn next_region_var(&mut self, _span: hir_ty::Span) -> Region<'db> {489                self.types.regions.error490            }491        }492493        Some(self.ty(ty))494    }495496    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    }506507    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            true516        } else if let ExprOrPatId::ExprId(expr_id) = expr_id517            && let Expr::Block { tail: Some(tail), .. } = store[expr_id]518        {519            self.expr_id_is_diverging(store, infer, tail.into())520        } else {521            false522        }523    }524525    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_id533            .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    }540541    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) => infer550                .expr_adjustment(idx)551                .and_then(|adjusts| adjusts.last())552                .map(|adjust| adjust.target.as_ref()),553            ExprOrPatId::PatId(idx) => infer554                .pat_adjustment(idx)555                .and_then(|adjusts| adjusts.last())556                .map(|adjust| adjust.source.as_ref()),557        };558559        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    }563564    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    }575576    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    }588589    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            infer615                .pat_adjustment(pat_id.as_pat()?)?616                .iter()617                .map(|adjust| self.ty(adjust.source.as_ref()))618                .collect(),619        )620    }621622    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    }636637    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)?;644645        Some(self.resolve_impl_method_or_trait_def(db, f_in_trait, substs))646    }647648    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    }671672    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    }680681    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    }691692    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        None704    }705706    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    }736737    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    }749750    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    }762763    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.RangeFromCopy778                } else {779                    lang_items.RangeFrom780                }781            }782            (RangeOp::Exclusive, true, true) => {783                if has_new_range {784                    lang_items.RangeCopy785                } else {786                    lang_items.Range787                }788            }789            (RangeOp::Inclusive, false, true) => {790                if has_new_range {791                    lang_items.RangeToInclusiveCopy792                } else {793                    lang_items.RangeToInclusive794                }795            }796            (RangeOp::Inclusive, true, true) => {797                if has_new_range {798                    lang_items.RangeInclusiveCopy799                } else {800                    lang_items.RangeInclusiveStruct801                }802            }803            // [E0586] inclusive ranges must be bounded at the end804            (RangeOp::Inclusive, false, false) => None,805            (RangeOp::Inclusive, true, false) => None,806        }807    }808809    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()?)?;815816        let into_future_trait = self817            .resolver818            .resolve_known_trait(db, &path![core::future::IntoFuture])819            .map(Trait::from);820821        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        }837838        let poll_fn = self.lang_items(db).FuturePoll?;839        // HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself840        // 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    }844845    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        };870871        let ty = self.ty_of_expr(prefix_expr.expr()?)?;872873        // HACK: subst for all methods coincides with that for their trait because the methods874        // don't have any generic parameters, so we skip building another subst for the methods.875        let substs = GenericArgs::new_from_slice(&[ty.into()]);876877        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))878    }879880    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);888889        let (_index_trait, index_fn) = (lang_items.Index?, lang_items.Index_index?);890        let op_fn = self891            .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 methods901        // 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    }905906    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()?)?;914915        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()` itself918        // 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()]);920921        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))922    }923924    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()?)?;930931        let op_fn = self.lang_items(db).TryTraitBranch?;932        // HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself933        // doesn't have any generic parameters, so we skip building another subst for `branch()`.934        let substs = GenericArgs::new_from_slice(&[ty.into()]);935936        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))937    }938939    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);948949        let ast_name = field.field_name()?;950        let local_name = ast_name.as_name();951        let local = if field.name_ref().is_some() {952            None953        } else {954            // Shorthand syntax, resolve to the local955            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    }987988    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    }10111012    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()?;10211022        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    }10331034    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()?;10411042        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        };10521053        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    }10671068    pub(crate) fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option<crate::TypeParam> {1069        let name = name.as_name();1070        self.resolver1071            .all_generic_params()1072            .find_map(|(params, parent)| params.find_type_by_name(&name, parent))1073            .map(crate::TypeParam::from)1074    }10751076    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)?;10841085        let env = self.trait_environment(db);10861087        let interner = DbInterner::new_with(db, env.krate);1088        let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);10891090        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                };11381139            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        None1148    }11491150    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();11571158        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) = self1178                                            .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                    };12061207                    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            None1271        })();1272        if resolved.is_some() {1273            return resolved;1274        }12751276        // 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 = path1281            .parent_path()1282            .and_then(|p| collector.lower_path(p, &mut ExprCollector::impl_trait_error_allocator));1283        let (store, _) = collector.store.finish();12841285        // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are1286        // 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        }12931294        let meta_path = path1295            .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);13031304        // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are1305        // 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() => path1309                    .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::str1322                //     str::len();        // as primitive type str1323                //     str::no_exist_item(); // as primitive type str1324                // }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 module1334                            .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 complex1344                // due to the interactions with associated items of `impl`s and associated items of associated1345                // 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 attribute1350            // in this case we have to check for inert/builtin attributes and tools and prioritize1351            // resolution of attributes over other namespaces1352            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                }13571358                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) = self1371                            .resolver1372                            .def_map()1373                            .derive_helpers_in_scope(InFile::new(self.file_id, ast_id))1374                        {1375                            // FIXME: Multiple derives can have the same helper1376                            let name_ref = name_ref.as_name();1377                            for (macro_id, mut helpers) in1378                                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 wrong1398                // but there is no benefit in differentiating these two cases for the time being1399                None => path1400                    .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    }14771478    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    }14981499    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()?;15061507        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    }15141515    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()?;15221523        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])?;15271528        let res = self.missing_fields(db, substs, variant, matched_fields);1529        Some(res)1530    }15311532    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()?;15391540        let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;1541        let substs = infer.pat_ty(pat_id).as_adt()?.1;15421543        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    }15481549    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()?;15561557        let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;1558        let substs = infer.pat_ty(pat_id).as_adt()?.1;15591560        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    }15651566    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);15751576        missing_fields1577            .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    }15851586    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    }15911592    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::No1604                })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        false1613    }16141615    /// 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    }16401641    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    }16561657    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    }16801681    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    }16881689    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).01696    }16971698    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    }17171718    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    }17331734    fn lang_items<'a>(&self, db: &'a dyn HirDatabase) -> &'a LangItems {1735        hir_def::lang_item::lang_items(db, self.resolver.krate())1736    }17371738    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}17421743// Note: the `ExprId` here does not need to be accurate, what's important is that it points at the same1744// 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}17631764fn 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    scopes1772        .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            }17791780            // FIXME handle attribute expansion1781            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 scope1792        .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}17971798// XXX: during completion, cursor might be outside of any particular1799// 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 = scopes1809        .scope_by_expr()1810        .iter()1811        .filter_map(|(id, scope)| {1812            let source = source_map.expr_syntax(id).ok()?;1813            // FIXME: correctly handle macro expansion1814            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_range1823        });18241825    child_scopes1826        .max_by(|&(r1, _, _), &(r2, _, _)| {1827            if r1.contains_range(r2) {1828                std::cmp::Ordering::Greater1829            } else if r2.contains_range(r1) {1830                std::cmp::Ordering::Less1831            } else {1832                r1.start().cmp(&r2.start())1833            }1834        })1835        .map(|(_ptr, scope, expr)| (*scope, expr))1836}18371838#[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}18491850#[inline]1851pub(crate) fn resolve_hir_path_as_attr_macro(1852    db: &dyn HirDatabase,1853    resolver: &Resolver<'_>,1854    path: &Path,1855) -> Option<Macro> {1856    resolver1857        .resolve_path_as_macro(db, path.mod_path()?, Some(MacroSubNs::Attr))1858        .map(|(it, _)| it)1859        .map(Into::into)1860}18611862fn 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                            None1896                        }1897                    }1898                    None => Some((ty, None)),1899                }1900            }1901        }?;19021903        // If we are in a TypeNs for a Trait, and we have an unresolved name, try to resolve it as a type1904        // 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        }19111912        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) => resolver1926                .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    };19411942    let body_owner = resolver.expression_store_owner();1943    let values = || resolve_hir_value_path(db, resolver, body_owner, infer_body, path, hygiene);19441945    let items = || {1946        resolver1947            .resolve_module_path_in_items(db, path.mod_path()?)1948            .take_types()1949            .map(|it| PathResolution::Def(it.into()))1950    };19511952    let macros = || {1953        resolver1954            .resolve_path_as_macro(db, path.mod_path()?, None)1955            .map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into())))1956    };19571958    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        };19741975        if res.any().is_some() {1976            res1977        } 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}19841985fn 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()),

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.