src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs RUST 2,239 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,239.
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, LoweringMode, ModuleDefId, StructId,17    VariantId,18    expr_store::{19        Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, HygieneId,20        lower::{ExprCollector, lower_generic_params},21        path::Path,22        scope::{ExprScopes, ScopeId},23    },24    hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId, generics::GenericParams},25    lang_item::LangItems,26    nameres::MacroSubNs,27    resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs, resolver_for_scope},28    type_ref::{Mutability, TypeRefId},29    visibility::Visibility,30};31use hir_expand::{32    HirFileId, InFile,33    mod_path::{ModPath, PathKind, path},34    name::{AsName, Name},35};36use hir_ty::{37    Adjustment, InferBodyId, InferenceResult, LifetimeElisionKind, LifetimeLoweringMode,38    ParamEnvAndCrate, TyLoweringContext, TyLoweringInferVarsCtx,39    diagnostics::{40        InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields,41        unsafe_operations,42    },43    lang_items::lang_items_for_bin_op,44    method_resolution::{self, CandidateId},45    next_solver::{46        AliasTy, DbInterner, DefaultAny, EarlyBinder, ErrorGuaranteed, GenericArgs, ParamEnv,47        Region, Ty, TyKind, TypingMode, infer::DbInternerInferExt,48    },49    traits::{WherePredicateEvaluation, structurally_normalize_ty, where_predicate_must_hold},50};51use intern::sym;52use itertools::Itertools;53use rustc_hash::FxHashSet;54use rustc_type_ir::{55    AliasTyKind,56    inherent::{IntoKind, Ty as _},57};58use smallvec::SmallVec;59use stdx::never;60use syntax::{61    SyntaxKind, SyntaxNode, TextRange, TextSize,62    ast::{self, AstNode, RangeItem, RangeOp},63};6465use crate::{66    Adt, AnyFunctionId, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const,67    DeriveHelper, EnumVariant, Field, Function, GenericSubstitution, Local, Macro, ModuleDef,68    PredicateEvaluationResult, SemanticsImpl, Static, Struct, ToolModule, Trait, TupleField, Type,69    TypeAlias, TypeOwnerId,70    db::HirDatabase,71    semantics::{PathResolution, PathResolutionPerNs},72};7374/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of75/// original source files. It should not be used inside the HIR itself.76#[derive(Debug)]77pub(crate) struct SourceAnalyzer<'db> {78    pub(crate) file_id: HirFileId,79    pub(crate) resolver: Resolver<'db>,80    pub(crate) body_or_sig: Option<BodyOrSig<'db>>,81    pub(crate) type_owner: TypeOwnerId,82    pub(crate) infer_body: Option<InferBodyId<'db>>,83}8485#[derive(Debug)]86pub(crate) enum BodyOrSig<'db> {87    Body {88        def: DefWithBodyId,89        body: &'db Body,90        source_map: &'db BodySourceMap,91        infer: Option<&'db InferenceResult<'db>>,92    },93    VariantFields {94        def: VariantId,95        store: &'db ExpressionStore,96        source_map: &'db ExpressionStoreSourceMap,97        infer: Option<&'db InferenceResult<'db>>,98    },99    Sig {100        def: GenericDefId,101        store: &'db ExpressionStore,102        source_map: &'db ExpressionStoreSourceMap,103        infer: Option<&'db InferenceResult<'db>>,104        #[expect(dead_code)]105        generics: &'db GenericParams,106    },107}108109impl<'db> SourceAnalyzer<'db> {110    pub(crate) fn new_for_body(111        db: &'db dyn HirDatabase,112        def: DefWithBodyId,113        node: InFile<&SyntaxNode>,114        offset: Option<TextSize>,115    ) -> SourceAnalyzer<'db> {116        Self::new_for_body_(db, def, node, offset, Some(InferenceResult::of(db, def)))117    }118119    pub(crate) fn new_for_body_no_infer(120        db: &'db dyn HirDatabase,121        def: DefWithBodyId,122        node: InFile<&SyntaxNode>,123        offset: Option<TextSize>,124    ) -> SourceAnalyzer<'db> {125        Self::new_for_body_(db, def, node, offset, None)126    }127128    pub(crate) fn new_for_body_(129        db: &'db dyn HirDatabase,130        def: DefWithBodyId,131        node @ InFile { file_id, .. }: InFile<&SyntaxNode>,132        offset: Option<TextSize>,133        infer: Option<&'db InferenceResult<'db>>,134    ) -> SourceAnalyzer<'db> {135        let (body, source_map) = Body::with_source_map(db, def);136        let scopes = ExprScopes::of(db, def);137        let scope = match offset {138            None => scope_for(db, scopes, source_map, node),139            Some(offset) => {140                debug_assert!(141                    node.text_range().contains_inclusive(offset),142                    "{:?} not in {:?}",143                    offset,144                    node.text_range()145                );146                scope_for_offset(db, scopes, source_map, node.file_id, offset)147            }148        };149        let (scope, _expr) = scope.unzip();150        let resolver = resolver_for_scope(db, def, scope);151        SourceAnalyzer {152            resolver,153            body_or_sig: Some(BodyOrSig::Body { def, body, source_map, infer }),154            file_id,155            type_owner: def.generic_def(db).into(),156            infer_body: Some(def.into()),157        }158    }159160    pub(crate) fn new_generic_def(161        db: &'db dyn HirDatabase,162        sema: &SemanticsImpl<'db>,163        def: GenericDefId,164        node: InFile<&SyntaxNode>,165        offset: Option<TextSize>,166    ) -> SourceAnalyzer<'db> {167        Self::new_generic_def_(db, sema, def, node, offset, true)168    }169170    pub(crate) fn new_generic_def_no_infer(171        db: &'db dyn HirDatabase,172        sema: &SemanticsImpl<'db>,173        def: GenericDefId,174        node: InFile<&SyntaxNode>,175        offset: Option<TextSize>,176    ) -> SourceAnalyzer<'db> {177        Self::new_generic_def_(db, sema, def, node, offset, false)178    }179180    pub(crate) fn new_generic_def_(181        db: &'db dyn HirDatabase,182        sema: &SemanticsImpl<'db>,183        def: GenericDefId,184        node @ InFile { file_id, .. }: InFile<&SyntaxNode>,185        offset: Option<TextSize>,186        infer: bool,187    ) -> SourceAnalyzer<'db> {188        let (generics, store, source_map) = GenericParams::with_source_map(db, def);189        let scopes = ExprScopes::of(db, def);190        let scope = match offset {191            None => scope_for(db, scopes, source_map, node),192            Some(offset) => {193                debug_assert!(194                    node.text_range().contains_inclusive(offset),195                    "{:?} not in {:?}",196                    offset,197                    node.text_range()198                );199                scope_for_offset(db, scopes, source_map, node.file_id, offset)200            }201        };202        let (scope, expr) = scope.unzip();203        let resolver = resolver_for_scope(db, def, scope);204        let infer_body = expr.and_then(|expr| {205            sema.infer_body_for_expr_or_pat(206                ExpressionStoreOwnerId::Signature(def),207                store,208                expr.into(),209            )210        });211        let infer = if infer && let Some(infer_body) = infer_body {212            Some(InferenceResult::of(db, infer_body))213        } else {214            None215        };216        SourceAnalyzer {217            resolver,218            body_or_sig: Some(BodyOrSig::Sig { def, store, source_map, generics, infer }),219            file_id,220            type_owner: def.into(),221            infer_body,222        }223    }224225    pub(crate) fn new_variant_body(226        db: &'db dyn HirDatabase,227        sema: &SemanticsImpl<'db>,228        def: VariantId,229        node @ InFile { file_id, .. }: InFile<&SyntaxNode>,230        offset: Option<TextSize>,231        infer: bool,232    ) -> SourceAnalyzer<'db> {233        let (fields, source_map) = def.fields_with_source_map(db);234        let scopes = ExprScopes::of(db, def);235        let scope = match offset {236            None => scope_for(db, scopes, source_map, node),237            Some(offset) => {238                debug_assert!(239                    node.text_range().contains_inclusive(offset),240                    "{:?} not in {:?}",241                    offset,242                    node.text_range()243                );244                scope_for_offset(db, scopes, source_map, node.file_id, offset)245            }246        };247        let (scope, expr) = scope.unzip();248        let resolver = resolver_for_scope(db, def, scope);249        let infer_body = expr.and_then(|expr| {250            sema.infer_body_for_expr_or_pat(251                ExpressionStoreOwnerId::VariantFields(def),252                &fields.store,253                expr.into(),254            )255        });256        let infer = if infer && let Some(infer_body) = infer_body {257            Some(InferenceResult::of(db, infer_body))258        } else {259            None260        };261        SourceAnalyzer {262            resolver,263            body_or_sig: Some(BodyOrSig::VariantFields {264                def,265                store: &fields.store,266                source_map,267                infer,268            }),269            file_id,270            type_owner: GenericDefId::from(def.adt_id(db)).into(),271            infer_body,272        }273    }274275    pub(crate) fn new_for_resolver(276        resolver: Resolver<'db>,277        node: InFile<&SyntaxNode>,278    ) -> SourceAnalyzer<'db> {279        SourceAnalyzer {280            type_owner: resolver281                .generic_def()282                .map(Into::into)283                .unwrap_or_else(|| TypeOwnerId::NoParams(resolver.krate())),284            resolver,285            body_or_sig: None,286            file_id: node.file_id,287            infer_body: None,288        }289    }290291    fn owner(&self) -> Option<ExpressionStoreOwnerId> {292        self.body_or_sig.as_ref().map(|it| match *it {293            BodyOrSig::VariantFields { def, .. } => def.into(),294            BodyOrSig::Sig { def, .. } => def.into(),295            BodyOrSig::Body { def, .. } => def.into(),296        })297    }298299    fn infer(&self) -> Option<&'db InferenceResult<'db>> {300        self.body_or_sig.as_ref().and_then(|it| match *it {301            BodyOrSig::VariantFields { infer, .. }302            | BodyOrSig::Sig { infer, .. }303            | BodyOrSig::Body { infer, .. } => infer,304        })305    }306307    pub(crate) fn ty(&self, ty: Ty<'db>) -> Type<'db> {308        Type { owner: self.type_owner, ty: EarlyBinder::bind(ty) }309    }310311    pub(crate) fn def(312        &self,313    ) -> Option<(314        ExpressionStoreOwnerId,315        &'db ExpressionStore,316        &'db ExpressionStoreSourceMap,317        Option<&'db InferenceResult<'db>>,318    )> {319        self.body_or_sig.as_ref().map(|it| match *it {320            BodyOrSig::VariantFields { def, store, source_map, infer, .. } => {321                (def.into(), store, source_map, infer)322            }323            BodyOrSig::Sig { def, store, source_map, infer, .. } => {324                (def.into(), store, source_map, infer)325            }326            BodyOrSig::Body { def, body, source_map, infer, .. } => {327                (def.into(), &body.store, &source_map.store, infer)328            }329        })330    }331332    pub(crate) fn store(&self) -> Option<&'db ExpressionStore> {333        self.body_or_sig.as_ref().map(|it| match *it {334            BodyOrSig::Sig { store, .. } => store,335            BodyOrSig::VariantFields { store, .. } => store,336            BodyOrSig::Body { body, .. } => &body.store,337        })338    }339340    pub(crate) fn store_sm(&self) -> Option<&'db ExpressionStoreSourceMap> {341        self.body_or_sig.as_ref().map(|it| match *it {342            BodyOrSig::Sig { source_map, .. } => source_map,343            BodyOrSig::VariantFields { source_map, .. } => source_map,344            BodyOrSig::Body { source_map, .. } => &source_map.store,345        })346    }347348    fn param_and<'a>(&self, param_env: ParamEnv<'a>) -> ParamEnvAndCrate<'a> {349        ParamEnvAndCrate { param_env, krate: self.resolver.krate() }350    }351352    fn trait_environment(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> {353        self.param_and(self.body_or_sig.as_ref().map_or_else(ParamEnv::empty, |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    }366367    pub(crate) fn evaluate_where_clause(368        &self,369        db: &'db dyn HirDatabase,370        where_clause: ast::WhereClause,371    ) -> PredicateEvaluationResult {372        let Some(owner) = self.owner() else {373            // FIXME374            return PredicateEvaluationResult::unsupported(375                "predicate evaluation is only supported inside an item",376            );377        };378        let generic_def = owner.generic_def(db);379        let module = generic_def.module(db);380        let (store, params, _) = lower_generic_params(381            db,382            module,383            generic_def,384            self.file_id,385            None,386            Some(where_clause),387            LoweringMode::Ide,388        );389        let predicates = params.where_predicates();390        if predicates.is_empty() {391            return PredicateEvaluationResult::holds("predicate does not impose any obligations");392        }393394        let env = self.trait_environment(db);395        for predicate in predicates {396            match where_predicate_must_hold(397                db,398                &self.resolver,399                &store,400                owner,401                generic_def,402                env,403                predicate,404            ) {405                WherePredicateEvaluation::Holds | WherePredicateEvaluation::NoObligations => {}406                WherePredicateEvaluation::HasErrors => {407                    return PredicateEvaluationResult::invalid(408                        "predicate contains unresolved names or invalid type syntax",409                    );410                }411                WherePredicateEvaluation::NotProven => {412                    return PredicateEvaluationResult::not_proven("predicate is not known to hold");413                }414            }415        }416417        PredicateEvaluationResult::holds("predicate holds")418    }419420    pub(crate) fn expr_id(&self, expr: ast::Expr) -> Option<ExprOrPatId> {421        let src = InFile { file_id: self.file_id, value: expr };422        self.store_sm()?.node_expr(src.as_ref())423    }424425    fn pat_id(&self, pat: &ast::Pat) -> Option<ExprOrPatId> {426        let src = InFile { file_id: self.file_id, value: pat };427        self.store_sm()?.node_pat(src)428    }429430    fn type_id(&self, pat: &ast::Type) -> Option<TypeRefId> {431        let src = InFile { file_id: self.file_id, value: pat };432        self.store_sm()?.node_type(src)433    }434435    fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingId> {436        let pat_id = self.pat_id(&pat.clone().into())?;437        if let Pat::Bind { id, .. } = self.store()?[pat_id.as_pat()?] { Some(id) } else { None }438    }439440    pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment]> {441        // It is safe to omit destructuring assignments here because they have no adjustments (neither442        // expressions nor patterns).443        let expr_id = self.expr_id(expr.clone())?.as_expr()?;444        let infer = self.infer()?;445        infer.expr_adjustment(expr_id)446    }447448    pub(crate) fn type_of_type(449        &self,450        db: &'db dyn HirDatabase,451        ty: &ast::Type,452    ) -> Option<Type<'db>> {453        let interner = DbInterner::new_no_crate(db);454455        let type_ref = self.type_id(ty)?;456457        let generic_def = self.resolver.generic_def()?;458        let generics = OnceCell::new();459        let mut vars_cts = VarsCtx { types: interner.default_types(), infer: self.infer() };460        let ty = TyLoweringContext::new(461            db,462            &self.resolver,463            self.store()?,464            self.resolver.expression_store_owner().unwrap_or_else(|| generic_def.into()),465            generic_def,466            &generics,467            // FIXME: Is this correct here? Anyway that should impact mostly diagnostics, which we don't emit here468            // (this can impact the lifetimes generated, e.g. in `const` they won't be `'static`, but this seems like a469            // small problem).470            LifetimeElisionKind::Infer,471            LifetimeLoweringMode::LateParam,472        )473        .with_interning_mode(LoweringMode::Ide)474        .with_infer_vars_behavior(Some(&mut vars_cts))475        .lower_ty(type_ref);476477        struct VarsCtx<'a, 'db> {478            types: &'a DefaultAny<'db>,479            infer: Option<&'a InferenceResult<'db>>,480        }481482        impl<'db> TyLoweringInferVarsCtx<'db> for VarsCtx<'_, 'db> {483            fn next_ty_var(&mut self, span: hir_ty::Span) -> Ty<'db> {484                if let hir_ty::Span::TypeRefId(type_ref) = span485                    && let Some(ty) =486                        self.infer.and_then(|infer| infer.type_of_type_placeholder(type_ref))487                {488                    ty489                } else {490                    self.types.types.error491                }492            }493            fn next_const_var(&mut self, _span: hir_ty::Span) -> hir_ty::next_solver::Const<'db> {494                self.types.consts.error495            }496            fn next_region_var(&mut self, _span: hir_ty::Span) -> Region<'db> {497                self.types.regions.error498            }499        }500501        Some(self.ty(ty))502    }503504    pub(crate) fn expr_is_diverging(505        &self,506        _db: &'db dyn HirDatabase,507        expr: &ast::Expr,508    ) -> Option<bool> {509        let expr_id = self.expr_id(expr.clone())?;510        let store = self.store()?;511        let infer = self.infer()?;512        Some(self.expr_id_is_diverging(store, infer, expr_id))513    }514515    fn expr_id_is_diverging(516        &self,517        store: &ExpressionStore,518        infer: &InferenceResult<'_>,519        expr_id: ExprOrPatId,520    ) -> bool {521        // FIXME: This is an approximation, perhaps we need to store a set of diverging exprs in inference?522        if infer.type_of_expr_or_pat(expr_id).is_some_and(|ty| ty.is_never()) {523            true524        } else if let ExprOrPatId::ExprId(expr_id) = expr_id525            && let Expr::Block { tail: Some(tail), .. } = store[expr_id]526        {527            self.expr_id_is_diverging(store, infer, tail.into())528        } else {529            false530        }531    }532533    pub(crate) fn type_of_expr(534        &self,535        _db: &'db dyn HirDatabase,536        expr: &ast::Expr,537    ) -> Option<(Type<'db>, Option<Type<'db>>)> {538        let expr_id = self.expr_id(expr.clone())?;539        let infer = self.infer()?;540        let coerced = expr_id541            .as_expr()542            .and_then(|expr_id| infer.expr_adjustment(expr_id))543            .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.as_ref()));544        let ty = infer.expr_or_pat_ty(expr_id);545        let mk_ty = |ty: Ty<'db>| self.ty(ty);546        Some((mk_ty(ty), coerced.map(mk_ty)))547    }548549    pub(crate) fn type_of_pat(550        &self,551        _db: &'db dyn HirDatabase,552        pat: &ast::Pat,553    ) -> Option<(Type<'db>, Option<Type<'db>>)> {554        let expr_or_pat_id = self.pat_id(pat)?;555        let infer = self.infer()?;556        let coerced = match expr_or_pat_id {557            ExprOrPatId::ExprId(idx) => infer558                .expr_adjustment(idx)559                .and_then(|adjusts| adjusts.last())560                .map(|adjust| adjust.target.as_ref()),561            ExprOrPatId::PatId(idx) => infer562                .pat_adjustment(idx)563                .and_then(|adjusts| adjusts.last())564                .map(|adjust| adjust.source.as_ref()),565        };566567        let ty = infer.expr_or_pat_ty(expr_or_pat_id);568        let mk_ty = |ty: Ty<'db>| self.ty(ty);569        Some((mk_ty(ty), coerced.map(mk_ty)))570    }571572    pub(crate) fn type_of_binding_in_pat(573        &self,574        _db: &'db dyn HirDatabase,575        pat: &ast::IdentPat,576    ) -> Option<Type<'db>> {577        let binding_id = self.binding_id_of_pat(pat)?;578        let infer = self.infer()?;579        let ty = infer.binding_ty(binding_id);580        let mk_ty = |ty: Ty<'db>| self.ty(ty);581        Some(mk_ty(ty))582    }583584    pub(crate) fn type_of_self(585        &self,586        _db: &'db dyn HirDatabase,587        _param: &ast::SelfParam,588    ) -> Option<Type<'db>> {589        let binding = match self.body_or_sig.as_ref()? {590            BodyOrSig::Sig { .. } | BodyOrSig::VariantFields { .. } => return None,591            BodyOrSig::Body { body, .. } => body.self_param?.formal,592        };593        let ty = self.infer()?.binding_ty(binding);594        Some(self.ty(ty))595    }596597    pub(crate) fn binding_mode_of_pat(598        &self,599        _db: &'db dyn HirDatabase,600        pat: &ast::IdentPat,601    ) -> Option<BindingMode> {602        let id = self.pat_id(&pat.clone().into())?;603        let infer = self.infer()?;604        Some(match infer.binding_mode(id.as_pat()?)? {605            hir_ty::BindingMode(hir_ty::ByRef::No, _) => BindingMode::Move,606            hir_ty::BindingMode(hir_ty::ByRef::Yes(hir_ty::next_solver::Mutability::Mut), _) => {607                BindingMode::Ref(Mutability::Mut)608            }609            hir_ty::BindingMode(hir_ty::ByRef::Yes(hir_ty::next_solver::Mutability::Not), _) => {610                BindingMode::Ref(Mutability::Shared)611            }612        })613    }614    pub(crate) fn pattern_adjustments(615        &self,616        _db: &'db dyn HirDatabase,617        pat: &ast::Pat,618    ) -> Option<SmallVec<[Type<'db>; 1]>> {619        let pat_id = self.pat_id(pat)?;620        let infer = self.infer()?;621        Some(622            infer623                .pat_adjustment(pat_id.as_pat()?)?624                .iter()625                .map(|adjust| self.ty(adjust.source.as_ref()))626                .collect(),627        )628    }629630    pub(crate) fn resolve_method_call_as_callable(631        &self,632        db: &'db dyn HirDatabase,633        call: &ast::MethodCallExpr,634    ) -> Option<Callable<'db>> {635        let expr_id = self.expr_id(call.clone().into())?.as_expr()?;636        let (func, args) = self.infer()?.method_resolution(expr_id)?;637        let interner = DbInterner::new_no_crate(db);638        let ty = db.value_ty(func.into())?.instantiate(interner, args).skip_norm_wip();639        let ty = self.ty(ty);640        let mut res = ty.as_callable(db)?;641        res.is_bound_method = true;642        Some(res)643    }644645    pub(crate) fn resolve_method_call(646        &self,647        db: &'db dyn HirDatabase,648        call: &ast::MethodCallExpr,649    ) -> Option<Function> {650        let expr_id = self.expr_id(call.clone().into())?.as_expr()?;651        let (f_in_trait, substs) = self.infer()?.method_resolution(expr_id)?;652653        Some(self.resolve_impl_method_or_trait_def(db, f_in_trait, substs))654    }655656    pub(crate) fn resolve_method_call_fallback(657        &self,658        db: &'db dyn HirDatabase,659        call: &ast::MethodCallExpr,660    ) -> Option<(Either<Function, Field>, Option<GenericSubstitution<'db>>)> {661        let expr_id = self.expr_id(call.clone().into())?.as_expr()?;662        let inference_result = self.infer()?;663        match inference_result.method_resolution(expr_id) {664            Some((f_in_trait, substs)) => {665                let (fn_, subst) =666                    self.resolve_impl_method_or_trait_def_with_subst(db, f_in_trait, substs);667                Some((668                    Either::Left(fn_),669                    GenericSubstitution::new_from_fn(fn_, subst, self.type_owner),670                ))671            }672            None => {673                inference_result.field_resolution(expr_id).and_then(Either::left).map(|field| {674                    (Either::Right(field.into()), self.field_subst(expr_id, inference_result, db))675                })676            }677        }678    }679680    pub(crate) fn resolve_expr_as_callable(681        &self,682        db: &'db dyn HirDatabase,683        call: &ast::Expr,684    ) -> Option<Callable<'db>> {685        let (orig, adjusted) = self.type_of_expr(db, &call.clone())?;686        adjusted.unwrap_or(orig).as_callable(db)687    }688689    pub(crate) fn resolve_field(690        &self,691        field: &ast::FieldExpr,692    ) -> Option<Either<Field, TupleField<'db>>> {693        let def = self.infer_body?;694        let expr_id = self.expr_id(field.clone().into())?.as_expr()?;695        self.infer()?.field_resolution(expr_id).map(|it| {696            it.map_either(Into::into, |f| TupleField { owner: def, tuple: f.tuple, index: f.index })697        })698    }699700    fn field_subst(701        &self,702        field_expr: ExprId,703        infer: &InferenceResult<'_>,704        _db: &'db dyn HirDatabase,705    ) -> Option<GenericSubstitution<'db>> {706        let body = self.store()?;707        if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] {708            let (adt, subst) = infer.type_of_expr_with_adjust(object_expr)?.as_adt()?;709            return Some(GenericSubstitution::new(adt.into(), subst, self.type_owner));710        }711        None712    }713714    pub(crate) fn resolve_field_fallback(715        &self,716        db: &'db dyn HirDatabase,717        field: &ast::FieldExpr,718    ) -> Option<(Either<Either<Field, TupleField<'db>>, Function>, Option<GenericSubstitution<'db>>)>719    {720        let def = self.infer_body?;721        let expr_id = self.expr_id(field.clone().into())?.as_expr()?;722        let inference_result = self.infer()?;723        match inference_result.field_resolution(expr_id) {724            Some(field) => match field {725                Either::Left(field) => Some((726                    Either::Left(Either::Left(field.into())),727                    self.field_subst(expr_id, inference_result, db),728                )),729                Either::Right(field) => Some((730                    Either::Left(Either::Right(TupleField {731                        owner: def,732                        tuple: field.tuple,733                        index: field.index,734                    })),735                    None,736                )),737            },738            None => inference_result.method_resolution(expr_id).map(|(f, substs)| {739                let (f, subst) = self.resolve_impl_method_or_trait_def_with_subst(db, f, substs);740                (Either::Right(f), GenericSubstitution::new_from_fn(f, subst, self.type_owner))741            }),742        }743    }744745    pub(crate) fn resolve_range_pat(746        &self,747        db: &'db dyn HirDatabase,748        range_pat: &ast::RangePat,749    ) -> Option<StructId> {750        self.resolve_range_struct(751            db,752            range_pat.op_kind()?,753            range_pat.start().is_some(),754            range_pat.end().is_some(),755        )756    }757758    pub(crate) fn resolve_range_expr(759        &self,760        db: &'db dyn HirDatabase,761        range_expr: &ast::RangeExpr,762    ) -> Option<StructId> {763        self.resolve_range_struct(764            db,765            range_expr.op_kind()?,766            range_expr.start().is_some(),767            range_expr.end().is_some(),768        )769    }770771    fn resolve_range_struct(772        &self,773        db: &'db dyn HirDatabase,774        op_kind: RangeOp,775        has_start: bool,776        has_end: bool,777    ) -> Option<StructId> {778        let has_new_range = self.resolver.top_level_def_map().features().new_range;779        let lang_items = self.lang_items(db);780        match (op_kind, has_start, has_end) {781            (RangeOp::Exclusive, false, false) => lang_items.RangeFull,782            (RangeOp::Exclusive, false, true) => lang_items.RangeTo,783            (RangeOp::Exclusive, true, false) => {784                if has_new_range {785                    lang_items.RangeFromCopy786                } else {787                    lang_items.RangeFrom788                }789            }790            (RangeOp::Exclusive, true, true) => {791                if has_new_range {792                    lang_items.RangeCopy793                } else {794                    lang_items.Range795                }796            }797            (RangeOp::Inclusive, false, true) => {798                if has_new_range {799                    lang_items.RangeToInclusiveCopy800                } else {801                    lang_items.RangeToInclusive802                }803            }804            (RangeOp::Inclusive, true, true) => {805                if has_new_range {806                    lang_items.RangeInclusiveCopy807                } else {808                    lang_items.RangeInclusiveStruct809                }810            }811            // [E0586] inclusive ranges must be bounded at the end812            (RangeOp::Inclusive, false, false) => None,813            (RangeOp::Inclusive, true, false) => None,814        }815    }816817    pub(crate) fn resolve_await_to_poll(818        &self,819        db: &'db dyn HirDatabase,820        await_expr: &ast::AwaitExpr,821    ) -> Option<Function> {822        let mut ty = self.ty_of_expr(await_expr.expr()?)?;823824        let into_future_trait = self825            .resolver826            .resolve_known_trait(db, &path![core::future::IntoFuture])827            .map(Trait::from);828829        if let Some(into_future_trait) = into_future_trait {830            let type_ = self.ty(ty);831            if type_.impls_trait(db, into_future_trait, &[]) {832                let items = into_future_trait.items(db);833                let into_future_type = items.into_iter().find_map(|item| match item {834                    AssocItem::TypeAlias(alias)835                        if alias.name(db) == Name::new_symbol_root(sym::IntoFuture) =>836                    {837                        Some(alias)838                    }839                    _ => None,840                })?;841                let future_trait = type_.normalize_trait_assoc_type(db, &[], into_future_type)?;842                ty = future_trait.ty.skip_binder();843            }844        }845846        let poll_fn = self.lang_items(db).FuturePoll?;847        // HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself848        // doesn't have any generic parameters, so we skip building another subst for `poll()`.849        let substs = GenericArgs::new_from_slice(&[ty.into()]);850        Some(self.resolve_impl_method_or_trait_def(db, poll_fn, substs))851    }852853    pub(crate) fn resolve_prefix_expr(854        &self,855        db: &'db dyn HirDatabase,856        prefix_expr: &ast::PrefixExpr,857    ) -> Option<Function> {858        let lang_items = self.lang_items(db);859        let (_op_trait, op_fn) = match prefix_expr.op_kind()? {860            ast::UnaryOp::Deref => {861                // This can be either `Deref::deref` or `DerefMut::deref_mut`.862                // Since deref kind is inferenced and stored in `InferenceResult.method_resolution`,863                // use that result to find out which one it is.864                let (deref_trait, deref) = (lang_items.Deref?, lang_items.Deref_deref?);865                self.infer()866                    .and_then(|infer| {867                        let expr = self.expr_id(prefix_expr.clone().into())?.as_expr()?;868                        let (func, _) = infer.method_resolution(expr)?;869                        let (deref_mut_trait, deref_mut) =870                            (lang_items.DerefMut?, lang_items.DerefMut_deref_mut?);871                        if func == deref_mut { Some((deref_mut_trait, deref_mut)) } else { None }872                    })873                    .unwrap_or((deref_trait, deref))874            }875            ast::UnaryOp::Not => (lang_items.Not?, lang_items.Not_not?),876            ast::UnaryOp::Neg => (lang_items.Neg?, lang_items.Neg_neg?),877        };878879        let ty = self.ty_of_expr(prefix_expr.expr()?)?;880881        // HACK: subst for all methods coincides with that for their trait because the methods882        // don't have any generic parameters, so we skip building another subst for the methods.883        let substs = GenericArgs::new_from_slice(&[ty.into()]);884885        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))886    }887888    pub(crate) fn resolve_index_expr(889        &self,890        db: &'db dyn HirDatabase,891        index_expr: &ast::IndexExpr,892    ) -> Option<Function> {893        let base_ty = self.ty_of_expr(index_expr.base()?)?;894        let index_ty = self.ty_of_expr(index_expr.index()?)?;895        let lang_items = self.lang_items(db);896897        let (_index_trait, index_fn) = (lang_items.Index?, lang_items.Index_index?);898        let op_fn = self899            .infer()900            .and_then(|infer| {901                let expr = self.expr_id(index_expr.clone().into())?.as_expr()?;902                let (func, _) = infer.method_resolution(expr)?;903                let (_index_mut_trait, index_mut_fn) =904                    (lang_items.IndexMut_index_mut?, lang_items.IndexMut_index_mut?);905                if func == index_mut_fn { Some(index_mut_fn) } else { None }906            })907            .unwrap_or(index_fn);908        // HACK: subst for all methods coincides with that for their trait because the methods909        // don't have any generic parameters, so we skip building another subst for the methods.910        let substs = GenericArgs::new_from_slice(&[base_ty.into(), index_ty.into()]);911        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))912    }913914    pub(crate) fn resolve_bin_expr(915        &self,916        db: &'db dyn HirDatabase,917        binop_expr: &ast::BinExpr,918    ) -> Option<Function> {919        let op = binop_expr.op_kind()?;920        let lhs = self.ty_of_expr(binop_expr.lhs()?)?;921        let rhs = self.ty_of_expr(binop_expr.rhs()?)?;922923        let (op_fn, _op_trait) = lang_items_for_bin_op(self.lang_items(db), op)924            .and_then(|(method, trait_)| method.zip(trait_))?;925        // HACK: subst for `index()` coincides with that for `Index` because `index()` itself926        // doesn't have any generic parameters, so we skip building another subst for `index()`.927        let substs = GenericArgs::new_from_slice(&[lhs.into(), rhs.into()]);928929        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))930    }931932    pub(crate) fn resolve_try_expr(933        &self,934        db: &'db dyn HirDatabase,935        try_expr: &ast::TryExpr,936    ) -> Option<Function> {937        let ty = self.ty_of_expr(try_expr.expr()?)?;938939        let op_fn = self.lang_items(db).TryTraitBranch?;940        // HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself941        // doesn't have any generic parameters, so we skip building another subst for `branch()`.942        let substs = GenericArgs::new_from_slice(&[ty.into()]);943944        Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))945    }946947    pub(crate) fn resolve_record_field(948        &self,949        db: &'db dyn HirDatabase,950        field: &ast::RecordExprField,951    ) -> Option<(Field, Option<Local<'db>>, Type<'db>, GenericSubstitution<'db>)> {952        let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;953        let expr = ast::Expr::from(record_expr);954        let expr_id = self.store_sm()?.node_expr(InFile::new(self.file_id, &expr))?;955        let interner = DbInterner::new_no_crate(db);956957        let ast_name = field.field_name()?;958        let local_name = ast_name.as_name();959        let local = if field.name_ref().is_some() {960            None961        } else {962            // Shorthand syntax, resolve to the local963            let path = Path::from_known_path_with_no_generic(ModPath::from_segments(964                PathKind::Plain,965                once(local_name.clone()),966            ));967            match self.resolver.resolve_path_in_value_ns_fully(968                db,969                &path,970                name_hygiene(db, InFile::new(self.file_id, ast_name.syntax())),971            ) {972                Some(ValueNs::LocalBinding(binding_id)) => Some(Local {973                    binding_id,974                    parent: self.owner()?,975                    parent_infer: self.infer_body?,976                }),977                _ => None,978            }979        };980        let (adt, subst) = self.infer()?.type_of_expr_or_pat(expr_id)?.as_adt()?;981        let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?;982        let variant_data = variant.fields(db);983        let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };984        let field_ty = (*db.field_types(variant).get(field.local_id)?)985            .ty()986            .instantiate(interner, subst)987            .skip_norm_wip();988        Some((989            field.into(),990            local,991            self.ty(field_ty),992            GenericSubstitution::new(adt.into(), subst, self.type_owner),993        ))994    }995996    pub(crate) fn resolve_record_pat_field(997        &self,998        db: &'db dyn HirDatabase,999        field: &ast::RecordPatField,1000    ) -> Option<(Field, Type<'db>, GenericSubstitution<'db>)> {1001        let interner = DbInterner::new_no_crate(db);1002        let field_name = field.field_name()?.as_name();1003        let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;1004        let pat_id = self.pat_id(&record_pat.into())?;1005        let variant = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?;1006        let variant_data = variant.fields(db);1007        let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };1008        let (adt, subst) = self.infer()?.pat_ty(pat_id.as_pat()?).as_adt()?;1009        let field_ty = (*db.field_types(variant).get(field.local_id)?)1010            .ty()1011            .instantiate(interner, subst)1012            .skip_norm_wip();1013        Some((1014            field.into(),1015            self.ty(field_ty),1016            GenericSubstitution::new(adt.into(), subst, self.type_owner),1017        ))1018    }10191020    pub(crate) fn resolve_tuple_struct_pat_fields(1021        &self,1022        db: &'db dyn HirDatabase,1023        tuple_struct_pat: &ast::TupleStructPat,1024    ) -> Option<Vec<(Field, Type<'db>)>> {1025        let interner = DbInterner::new_no_crate(db);1026        let pat_id = self.pat_id(&tuple_struct_pat.clone().into())?;1027        let variant_id = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?;1028        let (_adt, substs) = self.infer()?.pat_ty(pat_id.as_pat()?).as_adt()?;10291030        Some(1031            db.field_types(variant_id)1032                .iter()1033                .map(|(local_id, field)| {1034                    let def = Field { parent: variant_id.into(), id: local_id };1035                    let ty = field.ty().instantiate(interner, substs).skip_norm_wip();1036                    (def, self.ty(ty))1037                })1038                .collect(),1039        )1040    }10411042    pub(crate) fn resolve_bind_pat_to_const(1043        &self,1044        db: &'db dyn HirDatabase,1045        pat: &ast::IdentPat,1046    ) -> Option<ModuleDef> {1047        let expr_or_pat_id = self.pat_id(&pat.clone().into())?;1048        let store = self.store()?;10491050        let path = match expr_or_pat_id {1051            ExprOrPatId::ExprId(idx) => match &store[idx] {1052                Expr::Path(path) => path,1053                _ => return None,1054            },1055            ExprOrPatId::PatId(idx) => match &store[idx] {1056                Pat::Path(path) => path,1057                _ => return None,1058            },1059        };10601061        let store_owner = self.resolver.expression_store_owner();1062        let (res, _) = resolve_hir_value_path(1063            db,1064            &self.resolver,1065            store_owner,1066            self.infer_body,1067            path,1068            HygieneId::ROOT,1069        )?;1070        match res {1071            PathResolution::Def(def) => Some(def),1072            _ => None,1073        }1074    }10751076    pub(crate) fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option<crate::TypeParam> {1077        let name = name.as_name();1078        self.resolver1079            .all_generic_params()1080            .find_map(|(params, parent)| params.find_type_by_name(&name, parent))1081            .map(crate::TypeParam::from)1082    }10831084    pub(crate) fn resolve_offset_of_field(1085        &self,1086        db: &'db dyn HirDatabase,1087        name_ref: &ast::NameRef,1088    ) -> Option<(Either<crate::EnumVariant, crate::Field>, GenericSubstitution<'db>)> {1089        let offset_of_expr = ast::OffsetOfExpr::cast(name_ref.syntax().parent()?)?;1090        let container = offset_of_expr.ty()?;1091        let container = self.type_of_type(db, &container)?;10921093        let env = self.trait_environment(db);10941095        let interner = DbInterner::new_with(db, env.krate);1096        let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);10971098        let mut container = Either::Right(container.ty.skip_binder());1099        for field_name in offset_of_expr.fields() {1100            if let Either::Right(container) = &mut container {1101                *container = structurally_normalize_ty(&infcx, *container, env.param_env);1102            }1103            let handle_variants =1104                |variant: VariantId, subst: GenericArgs<'db>, container: &mut _| {1105                    let fields = variant.fields(db);1106                    let field = fields.field(&field_name.as_name())?;1107                    let field_types = db.field_types(variant);1108                    *container = Either::Right(1109                        field_types[field].ty().instantiate(interner, subst).skip_norm_wip(),1110                    );1111                    let generic_def = match variant {1112                        VariantId::EnumVariantId(it) => it.loc(db).parent.into(),1113                        VariantId::StructId(it) => it.into(),1114                        VariantId::UnionId(it) => it.into(),1115                    };1116                    Some((1117                        Either::Right(Field { parent: variant.into(), id: field }),1118                        generic_def,1119                        subst,1120                    ))1121                };1122            let temp_ty = Ty::new_error(interner, ErrorGuaranteed);1123            let (field_def, generic_def, subst) =1124                match std::mem::replace(&mut container, Either::Right(temp_ty)) {1125                    Either::Left((variant_id, subst)) => {1126                        handle_variants(VariantId::from(variant_id), subst, &mut container)?1127                    }1128                    Either::Right(container_ty) => match container_ty.kind() {1129                        TyKind::Adt(adt_def, subst) => match adt_def.def_id() {1130                            AdtId::StructId(id) => {1131                                handle_variants(id.into(), subst, &mut container)?1132                            }1133                            AdtId::UnionId(id) => {1134                                handle_variants(id.into(), subst, &mut container)?1135                            }1136                            AdtId::EnumId(id) => {1137                                let variants = id.enum_variants(db);1138                                let variant = variants.variant(&field_name.as_name())?;1139                                container = Either::Left((variant, subst));1140                                (Either::Left(EnumVariant { id: variant }), id.into(), subst)1141                            }1142                        },1143                        _ => return None,1144                    },1145                };11461147            if field_name.syntax().text_range() == name_ref.syntax().text_range() {1148                return Some((1149                    field_def,1150                    GenericSubstitution::new(generic_def, subst, self.type_owner),1151                ));1152            }1153        }1154        never!("the `NameRef` is a child of the `OffsetOfExpr`, we should've visited it");1155        None1156    }11571158    pub(crate) fn resolve_path(1159        &self,1160        db: &'db dyn HirDatabase,1161        path: &ast::Path,1162    ) -> Option<(PathResolution<'db>, Option<GenericSubstitution<'db>>)> {1163        let parent = path.syntax().parent();1164        let parent = || parent.clone();11651166        let mut prefer_value_ns = parent().and_then(ast::PathExpr::cast).is_some();1167        let resolved = (|| {1168            let infer = self.infer()?;1169            if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) {1170                let expr_id = self.expr_id(path_expr.into())?;1171                if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_id) {1172                    let (assoc, subst) = match assoc {1173                        CandidateId::FunctionId(f_in_trait) => {1174                            match infer.type_of_expr_or_pat(expr_id) {1175                                None => {1176                                    let subst = GenericSubstitution::new(1177                                        f_in_trait.into(),1178                                        subs,1179                                        self.type_owner,1180                                    );1181                                    (AssocItem::Function(f_in_trait.into()), Some(subst))1182                                }1183                                Some(func_ty) => {1184                                    if let TyKind::FnDef(_fn_def, subs) = func_ty.kind() {1185                                        let (fn_, subst) = self1186                                            .resolve_impl_method_or_trait_def_with_subst(1187                                                db, f_in_trait, subs,1188                                            );1189                                        let subst = GenericSubstitution::new_from_fn(1190                                            fn_,1191                                            subst,1192                                            self.type_owner,1193                                        );1194                                        (AssocItem::Function(fn_), subst)1195                                    } else {1196                                        let subst = GenericSubstitution::new(1197                                            f_in_trait.into(),1198                                            subs,1199                                            self.type_owner,1200                                        );1201                                        (AssocItem::Function(f_in_trait.into()), Some(subst))1202                                    }1203                                }1204                            }1205                        }1206                        CandidateId::ConstId(const_id) => {1207                            let (konst, subst) =1208                                self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);1209                            let subst =1210                                GenericSubstitution::new(konst.into(), subst, self.type_owner);1211                            (AssocItem::Const(konst.into()), Some(subst))1212                        }1213                    };12141215                    return Some((PathResolution::Def(assoc.into()), subst));1216                }1217                if let Some(VariantId::EnumVariantId(variant)) =1218                    infer.variant_resolution_for_expr_or_pat(expr_id)1219                {1220                    return Some((1221                        PathResolution::Def(ModuleDef::EnumVariant(variant.into())),1222                        None,1223                    ));1224                }1225                prefer_value_ns = true;1226            } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {1227                let expr_or_pat_id = self.pat_id(&path_pat.into())?;1228                if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_or_pat_id)1229                {1230                    let (assoc, subst) = match assoc {1231                        CandidateId::ConstId(const_id) => {1232                            let (konst, subst) =1233                                self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);1234                            let subst =1235                                GenericSubstitution::new(konst.into(), subst, self.type_owner);1236                            (AssocItemId::from(konst), subst)1237                        }1238                        CandidateId::FunctionId(function_id) => (1239                            function_id.into(),1240                            GenericSubstitution::new(function_id.into(), subs, self.type_owner),1241                        ),1242                    };1243                    return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst)));1244                }1245                if let Some(VariantId::EnumVariantId(variant)) =1246                    infer.variant_resolution_for_expr_or_pat(expr_or_pat_id)1247                {1248                    return Some((1249                        PathResolution::Def(ModuleDef::EnumVariant(variant.into())),1250                        None,1251                    ));1252                }1253            } else if let Some(rec_lit) = parent().and_then(ast::RecordExpr::cast) {1254                let expr_id = self.expr_id(rec_lit.into())?;1255                if let Some(VariantId::EnumVariantId(variant)) =1256                    infer.variant_resolution_for_expr_or_pat(expr_id)1257                {1258                    return Some((1259                        PathResolution::Def(ModuleDef::EnumVariant(variant.into())),1260                        None,1261                    ));1262                }1263            } else {1264                let record_pat = parent().and_then(ast::RecordPat::cast).map(ast::Pat::from);1265                let tuple_struct_pat =1266                    || parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from);1267                if let Some(pat) = record_pat.or_else(tuple_struct_pat) {1268                    let pat_id = self.pat_id(&pat)?;1269                    let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id.as_pat()?);1270                    if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat {1271                        return Some((1272                            PathResolution::Def(ModuleDef::EnumVariant(variant.into())),1273                            None,1274                        ));1275                    }1276                }1277            }1278            None1279        })();1280        if resolved.is_some() {1281            return resolved;1282        }12831284        // FIXME: collectiong here shouldnt be necessary?1285        let mut collector =1286            ExprCollector::new(db, self.resolver.module(), self.file_id, LoweringMode::Ide);1287        let hir_path =1288            collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;1289        let parent_hir_path = path1290            .parent_path()1291            .and_then(|p| collector.lower_path(p, &mut ExprCollector::impl_trait_error_allocator));1292        let (store, _) = collector.store.finish();12931294        // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are1295        // trying to resolve foo::bar.1296        if let Some(use_tree) = parent().and_then(ast::UseTree::cast)1297            && use_tree.coloncolon_token().is_some()1298        {1299            return resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store)1300                .map(|it| (it, None));1301        }13021303        let meta_path = path1304            .syntax()1305            .ancestors()1306            .take_while(|it| {1307                let kind = it.kind();1308                ast::Path::can_cast(kind) || ast::Meta::can_cast(kind)1309            })1310            .last()1311            .and_then(ast::Meta::cast);13121313        // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are1314        // trying to resolve foo::bar.1315        if let Some(parent_hir_path) = parent_hir_path {1316            return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store) {1317                None if meta_path.is_some() => path1318                    .first_segment()1319                    .and_then(|it| it.name_ref())1320                    .and_then(|name_ref| {1321                        ToolModule::by_name(db, self.resolver.krate().into(), name_ref.text())1322                            .map(PathResolution::ToolModule)1323                    })1324                    .map(|it| (it, None)),1325                // Case the type name conflict with use module,1326                // e.g.1327                // ```1328                // use std::str;1329                // fn main() {1330                //     str::from_utf8();  // as module std::str1331                //     str::len();        // as primitive type str1332                //     str::no_exist_item(); // as primitive type str1333                // }1334                // ```1335                Some(it) if matches!(it, PathResolution::Def(ModuleDef::BuiltinType(_))) => {1336                    if let Some(mod_path) = hir_path.mod_path()1337                        && let Some(ModuleDefId::ModuleId(id)) =1338                            self.resolver.resolve_module_path_in_items(db, mod_path).take_types()1339                    {1340                        let parent_hir_name = parent_hir_path.segments().get(1).map(|it| it.name);1341                        let module = crate::Module { id };1342                        if module1343                            .scope(db, None)1344                            .into_iter()1345                            .any(|(name, _)| Some(&name) == parent_hir_name)1346                        {1347                            return Some((PathResolution::Def(ModuleDef::Module(module)), None));1348                        };1349                    }1350                    Some((it, None))1351                }1352                // FIXME: We do not show substitutions for parts of path, because this is really complex1353                // due to the interactions with associated items of `impl`s and associated items of associated1354                // types.1355                res => res.map(|it| (it, None)),1356            };1357        } else if let Some(meta_path) = meta_path {1358            // Case where we are resolving the final path segment of a path in an attribute1359            // in this case we have to check for inert/builtin attributes and tools and prioritize1360            // resolution of attributes over other namespaces1361            if let Some(name_ref) = path.as_single_name_ref() {1362                let builtin = BuiltinAttr::builtin(name_ref.text());1363                if builtin.is_some() {1364                    return builtin.map(|it| (PathResolution::BuiltinAttr(it), None));1365                }13661367                if let Some(attr) = meta_path.parent_attr() {1368                    let adt =1369                        attr.syntax().ancestors().find_map(ast::Item::cast).and_then(1370                            |it| match it {1371                                ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),1372                                ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),1373                                ast::Item::Union(it) => Some(ast::Adt::Union(it)),1374                                _ => None,1375                            },1376                        );1377                    if let Some(adt) = adt {1378                        let ast_id = self.file_id.ast_id_map(db).ast_id(&adt);1379                        if let Some(helpers) = self1380                            .resolver1381                            .def_map()1382                            .derive_helpers_in_scope(InFile::new(self.file_id, ast_id))1383                        {1384                            // FIXME: Multiple derives can have the same helper1385                            let name_ref = name_ref.as_name();1386                            for (macro_id, mut helpers) in1387                                helpers.iter().chunk_by(|(_, macro_id, ..)| macro_id).into_iter()1388                            {1389                                if let Some(idx) = helpers.position(|(name, ..)| *name == name_ref)1390                                {1391                                    return Some((1392                                        PathResolution::DeriveHelper(DeriveHelper {1393                                            derive: *macro_id,1394                                            idx: idx as u32,1395                                        }),1396                                        None,1397                                    ));1398                                }1399                            }1400                        }1401                    }1402                }1403            }1404            return match resolve_hir_path_as_attr_macro(db, &self.resolver, &hir_path) {1405                Some(m) => Some((PathResolution::Def(ModuleDef::Macro(m)), None)),1406                // this labels any path that starts with a tool module as the tool itself, this is technically wrong1407                // but there is no benefit in differentiating these two cases for the time being1408                None => path1409                    .first_segment()1410                    .and_then(|it| it.name_ref())1411                    .and_then(|name_ref| {1412                        ToolModule::by_name(db, self.resolver.krate().into(), name_ref.text())1413                            .map(PathResolution::ToolModule)1414                    })1415                    .map(|it| (it, None)),1416            };1417        }1418        if parent().is_some_and(|it| ast::Visibility::can_cast(it.kind())) {1419            // No substitution because only modules can be inside visibilities, and those have no generics.1420            resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store).map(|it| (it, None))1421        } else {1422            // Probably a type, no need to show substitutions for those.1423            let res = resolve_hir_path_(1424                db,1425                &self.resolver,1426                self.infer_body,1427                &hir_path,1428                prefer_value_ns,1429                name_hygiene(db, InFile::new(self.file_id, path.syntax())),1430                Some(&store),1431                false,1432            )1433            .any()?;1434            let subst = (|| {1435                let parent = parent()?;1436                let ty = if let Some(expr) = ast::Expr::cast(parent.clone()) {1437                    let expr_id = self.expr_id(expr)?;1438                    self.infer()?.type_of_expr_or_pat(expr_id)?1439                } else {1440                    let pat = ast::Pat::cast(parent)?;1441                    let pat_id = self.pat_id(&pat)?;1442                    self.infer()?.expr_or_pat_ty(pat_id)1443                };1444                let (subst, expected_resolution) = match ty.kind() {1445                    TyKind::Adt(adt_def, subst) => {1446                        let adt_id = adt_def.def_id();1447                        (1448                            GenericSubstitution::new(adt_id.into(), subst, self.type_owner),1449                            PathResolution::Def(ModuleDef::Adt(adt_id.into())),1450                        )1451                    }1452                    TyKind::Alias(AliasTy {1453                        kind: AliasTyKind::Projection { def_id },1454                        args,1455                        ..1456                    }) => {1457                        let assoc_id = def_id.0;1458                        (1459                            GenericSubstitution::new(assoc_id.into(), args, self.type_owner),1460                            PathResolution::Def(ModuleDef::TypeAlias(assoc_id.into())),1461                        )1462                    }1463                    TyKind::FnDef(fn_id, subst) => {1464                        let generic_def_id = match fn_id.0 {1465                            CallableDefId::StructId(id) => id.into(),1466                            CallableDefId::FunctionId(id) => id.into(),1467                            CallableDefId::EnumVariantId(_) => return None,1468                        };1469                        (1470                            GenericSubstitution::new(generic_def_id, subst, self.type_owner),1471                            PathResolution::Def(ModuleDefId::from(fn_id.0).into()),1472                        )1473                    }1474                    _ => return None,1475                };1476                if res != expected_resolution {1477                    // The user will not understand where we're coming from. This can happen (I think) with type aliases.1478                    return None;1479                }1480                Some(subst)1481            })();1482            Some((res, subst))1483        }1484    }14851486    pub(crate) fn resolve_hir_path_per_ns(1487        &self,1488        db: &'db dyn HirDatabase,1489        path: &ast::Path,1490    ) -> Option<PathResolutionPerNs<'db>> {1491        let mut collector =1492            ExprCollector::new(db, self.resolver.module(), self.file_id, LoweringMode::Ide);1493        let hir_path =1494            collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;1495        let (store, _) = collector.store.finish();1496        Some(resolve_hir_path_(1497            db,1498            &self.resolver,1499            self.infer_body,1500            &hir_path,1501            false,1502            name_hygiene(db, InFile::new(self.file_id, path.syntax())),1503            Some(&store),1504            true,1505        ))1506    }15071508    pub(crate) fn record_literal_missing_fields(1509        &self,1510        db: &'db dyn HirDatabase,1511        literal: &ast::RecordExpr,1512    ) -> Option<Vec<(Field, Type<'db>)>> {1513        let body = self.store()?;1514        let infer = self.infer()?;15151516        let expr_id = self.expr_id(literal.clone().into())?.as_expr()?;1517        let substs = infer.expr_ty(expr_id).as_adt()?.1;1518        let (variant, missing_fields) =1519            record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?;1520        let res = self.missing_fields(db, substs, variant, missing_fields);1521        Some(res)1522    }15231524    pub(crate) fn record_literal_matched_fields(1525        &self,1526        db: &'db dyn HirDatabase,1527        literal: &ast::RecordExpr,1528    ) -> Option<Vec<(Field, Type<'db>)>> {1529        let body = self.store()?;1530        let infer = self.infer()?;15311532        let expr_id = self.expr_id(literal.clone().into())?.as_expr()?;1533        let substs = infer.expr_ty(expr_id).as_adt()?.1;1534        let (variant, matched_fields) =1535            record_literal_matched_fields(db, infer, expr_id, &body[expr_id])?;15361537        let res = self.missing_fields(db, substs, variant, matched_fields);1538        Some(res)1539    }15401541    pub(crate) fn record_pattern_missing_fields(1542        &self,1543        db: &'db dyn HirDatabase,1544        pattern: &ast::RecordPat,1545    ) -> Option<Vec<(Field, Type<'db>)>> {1546        let body = self.store()?;1547        let infer = self.infer()?;15481549        let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;1550        let substs = infer.pat_ty(pat_id).as_adt()?.1;15511552        let (variant, missing_fields) =1553            record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;1554        let res = self.missing_fields(db, substs, variant, missing_fields);1555        Some(res)1556    }15571558    pub(crate) fn record_pattern_matched_fields(1559        &self,1560        db: &'db dyn HirDatabase,1561        pattern: &ast::RecordPat,1562    ) -> Option<Vec<(Field, Type<'db>)>> {1563        let body = self.store()?;1564        let infer = self.infer()?;15651566        let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;1567        let substs = infer.pat_ty(pat_id).as_adt()?.1;15681569        let (variant, matched_fields) =1570            record_pattern_matched_fields(db, infer, pat_id, &body[pat_id])?;1571        let res = self.missing_fields(db, substs, variant, matched_fields);1572        Some(res)1573    }15741575    fn missing_fields(1576        &self,1577        db: &'db dyn HirDatabase,1578        substs: GenericArgs<'db>,1579        variant: VariantId,1580        missing_fields: Vec<LocalFieldId>,1581    ) -> Vec<(Field, Type<'db>)> {1582        let interner = DbInterner::new_no_crate(db);1583        let field_types = db.field_types(variant);15841585        missing_fields1586            .into_iter()1587            .map(|local_id| {1588                let field = FieldId { parent: variant, local_id };1589                let ty = field_types[local_id].ty().instantiate(interner, substs).skip_norm_wip();1590                (field.into(), self.ty(ty))1591            })1592            .collect()1593    }15941595    pub(crate) fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {1596        let infer = self.infer()?;1597        let expr_id = self.expr_id(record_lit.into())?;1598        infer.variant_resolution_for_expr_or_pat(expr_id)1599    }16001601    pub(crate) fn is_unsafe_macro_call_expr(1602        &self,1603        db: &'db dyn HirDatabase,1604        macro_expr: InFile<&ast::MacroExpr>,1605    ) -> bool {1606        if let Some((def, body, sm, Some(infer))) = self.def()1607            && let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr)1608        {1609            let mut is_unsafe = false;1610            let mut walk_expr = |expr_id| {1611                unsafe_operations(db, infer, def, body, expr_id, &mut |_, inside_unsafe_block| {1612                    is_unsafe |= inside_unsafe_block == InsideUnsafeBlock::No1613                })1614            };1615            match expanded_expr {1616                ExprOrPatId::ExprId(expanded_expr) => walk_expr(expanded_expr),1617                ExprOrPatId::PatId(expanded_pat) => body.walk_exprs_in_pat(expanded_pat, walk_expr),1618            }1619            return is_unsafe;1620        }1621        false1622    }16231624    /// Returns the range of the implicit template argument and its resolution at the given `offset`1625    pub(crate) fn resolve_offset_in_format_args(1626        &self,1627        db: &'db dyn HirDatabase,1628        format_args: InFile<&ast::FormatArgsExpr>,1629        offset: TextSize,1630    ) -> Option<(TextRange, Option<PathResolution<'db>>)> {1631        let (hygiene, implicits) = self.store_sm()?.implicit_format_args(format_args)?;1632        implicits.iter().find(|(range, _)| range.contains_inclusive(offset)).map(|(range, name)| {1633            (1634                *range,1635                resolve_hir_value_path(1636                    db,1637                    &self.resolver,1638                    self.resolver.expression_store_owner(),1639                    self.infer_body,1640                    &Path::from_known_path_with_no_generic(ModPath::from_segments(1641                        PathKind::Plain,1642                        Some(name.clone()),1643                    )),1644                    hygiene,1645                )1646                .map(|(it, _)| it),1647            )1648        })1649    }16501651    pub(crate) fn resolve_offset_in_asm_template(1652        &self,1653        asm: InFile<&ast::AsmExpr>,1654        line: usize,1655        offset: TextSize,1656    ) -> Option<(ExpressionStoreOwnerId, (ExprId, TextRange, usize))> {1657        let (def, _, sm, _) = self.def()?;1658        let (expr, args) = sm.asm_template_args(asm)?;1659        Some(def).zip(1660            args.get(line)?1661                .iter()1662                .find(|(range, _)| range.contains_inclusive(offset))1663                .map(|(range, idx)| (expr, *range, *idx)),1664        )1665    }16661667    pub(crate) fn as_format_args_parts<'a>(1668        &'a self,1669        db: &'db dyn HirDatabase,1670        format_args: InFile<&ast::FormatArgsExpr>,1671    ) -> Option<impl Iterator<Item = (TextRange, Option<PathResolution<'db>>)> + 'a> {1672        let (hygiene, names) = self.store_sm()?.implicit_format_args(format_args)?;1673        Some(names.iter().map(move |(range, name)| {1674            (1675                *range,1676                resolve_hir_value_path(1677                    db,1678                    &self.resolver,1679                    self.resolver.expression_store_owner(),1680                    self.infer_body,1681                    &Path::from_known_path_with_no_generic(ModPath::from_segments(1682                        PathKind::Plain,1683                        Some(name.clone()),1684                    )),1685                    hygiene,1686                )1687                .map(|(it, _)| it),1688            )1689        }))1690    }16911692    pub(crate) fn as_asm_parts(1693        &self,1694        asm: InFile<&ast::AsmExpr>,1695    ) -> Option<(ExpressionStoreOwnerId, (ExprId, &[Vec<(TextRange, usize)>]))> {1696        let (def, _, sm, _) = self.def()?;1697        Some(def).zip(sm.asm_template_args(asm))1698    }16991700    fn resolve_impl_method_or_trait_def(1701        &self,1702        db: &'db dyn HirDatabase,1703        func: FunctionId,1704        substs: GenericArgs<'db>,1705    ) -> Function {1706        self.resolve_impl_method_or_trait_def_with_subst(db, func, substs).01707    }17081709    fn resolve_impl_method_or_trait_def_with_subst(1710        &self,1711        db: &'db dyn HirDatabase,1712        func: FunctionId,1713        substs: GenericArgs<'db>,1714    ) -> (Function, GenericArgs<'db>) {1715        let owner = match self.resolver.generic_def() {1716            Some(it) => it,1717            None => return (func.into(), substs),1718        };1719        let env = self.param_and(db.trait_environment(owner));1720        let (func, args) = db.lookup_impl_method(env, func, substs);1721        match func {1722            Either::Left(func) => (func.into(), args),1723            Either::Right((impl_, method)) => {1724                (Function { id: AnyFunctionId::BuiltinDeriveImplMethod { method, impl_ } }, args)1725            }1726        }1727    }17281729    fn resolve_impl_const_or_trait_def_with_subst(1730        &self,1731        db: &'db dyn HirDatabase,1732        const_id: ConstId,1733        subs: GenericArgs<'db>,1734    ) -> (ConstId, GenericArgs<'db>) {1735        let owner = match self.resolver.generic_def() {1736            Some(it) => it,1737            None => return (const_id, subs),1738        };1739        let env = self.param_and(db.trait_environment(owner));1740        let interner = DbInterner::new_with(db, env.krate);1741        let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);1742        method_resolution::lookup_impl_const(&infcx, env.param_env, const_id, subs)1743    }17441745    fn lang_items<'a>(&self, db: &'a dyn HirDatabase) -> &'a LangItems {1746        hir_def::lang_item::lang_items(db, self.resolver.krate())1747    }17481749    fn ty_of_expr(&self, expr: ast::Expr) -> Option<Ty<'db>> {1750        self.infer()?.type_of_expr_or_pat(self.expr_id(expr)?)1751    }1752}17531754// Note: the `ExprId` here does not need to be accurate, what's important is that it points at the same1755// inference root.1756fn scope_for(1757    db: &dyn HirDatabase,1758    scopes: &ExprScopes,1759    source_map: &ExpressionStoreSourceMap,1760    node: InFile<&SyntaxNode>,1761) -> Option<(ScopeId, ExprId)> {1762    node.ancestors_with_macros(db)1763        .take_while(|it| {1764            let kind = it.kind();1765            !ast::Item::can_cast(kind)1766                || ast::MacroCall::can_cast(kind)1767                || ast::Use::can_cast(kind)1768                || ast::AsmExpr::can_cast(kind)1769        })1770        .filter_map(|it| it.map(ast::Expr::cast).transpose())1771        .filter_map(|it| source_map.node_expr(it.as_ref())?.as_expr())1772        .find_map(|expr| scopes.scope_for(expr).map(|scope| (scope, expr)))1773}17741775fn scope_for_offset(1776    db: &dyn HirDatabase,1777    scopes: &ExprScopes,1778    source_map: &ExpressionStoreSourceMap,1779    from_file: HirFileId,1780    offset: TextSize,1781) -> Option<(ScopeId, ExprId)> {1782    scopes1783        .scope_by_expr()1784        .iter()1785        .filter_map(|(id, scope)| {1786            let InFile { file_id, value } = source_map.expr_syntax(id).ok()?;1787            if from_file == file_id {1788                return Some((value.text_range(), scope, id));1789            }17901791            // FIXME handle attribute expansion1792            let source = iter::successors(file_id.macro_file().map(|it| it.call_node(db)), |it| {1793                Some(it.file_id.macro_file()?.call_node(db))1794            })1795            .find(|it| it.file_id == from_file)1796            .filter(|it| it.kind() == SyntaxKind::MACRO_CALL)?;1797            Some((source.text_range(), scope, id))1798        })1799        .filter(|(expr_range, _scope, _expr)| {1800            expr_range.start() <= offset && offset <= expr_range.end()1801        })1802        // find containing scope1803        .min_by_key(|(expr_range, _scope, _expr)| expr_range.len())1804        .map(|(expr_range, scope, expr)| {1805            adjust(db, scopes, source_map, expr_range, from_file, offset).unwrap_or((*scope, expr))1806        })1807}18081809// XXX: during completion, cursor might be outside of any particular1810// expression. Try to figure out the correct scope...1811fn adjust(1812    db: &dyn HirDatabase,1813    scopes: &ExprScopes,1814    source_map: &ExpressionStoreSourceMap,1815    expr_range: TextRange,1816    from_file: HirFileId,1817    offset: TextSize,1818) -> Option<(ScopeId, ExprId)> {1819    let child_scopes = scopes1820        .scope_by_expr()1821        .iter()1822        .filter_map(|(id, scope)| {1823            let source = source_map.expr_syntax(id).ok()?;1824            // FIXME: correctly handle macro expansion1825            if source.file_id != from_file {1826                return None;1827            }1828            let root = source.file_syntax(db);1829            let node = source.value.to_node(&root);1830            Some((node.syntax().text_range(), scope, id))1831        })1832        .filter(|&(range, _, _)| {1833            range.start() <= offset && expr_range.contains_range(range) && range != expr_range1834        });18351836    child_scopes1837        .max_by(|&(r1, _, _), &(r2, _, _)| {1838            if r1.contains_range(r2) {1839                std::cmp::Ordering::Greater1840            } else if r2.contains_range(r1) {1841                std::cmp::Ordering::Less1842            } else {1843                r1.start().cmp(&r2.start())1844            }1845        })1846        .map(|(_ptr, scope, expr)| (*scope, expr))1847}18481849#[inline]1850pub(crate) fn resolve_hir_path<'db>(1851    db: &'db dyn HirDatabase,1852    resolver: &Resolver<'db>,1853    infer_body: Option<InferBodyId<'db>>,1854    path: &Path,1855    hygiene: HygieneId,1856    store: Option<&ExpressionStore>,1857) -> Option<PathResolution<'db>> {1858    resolve_hir_path_(db, resolver, infer_body, path, false, hygiene, store, false).any()1859}18601861#[inline]1862pub(crate) fn resolve_hir_path_as_attr_macro(1863    db: &dyn HirDatabase,1864    resolver: &Resolver<'_>,1865    path: &Path,1866) -> Option<Macro> {1867    resolver1868        .resolve_path_as_macro(db, path.mod_path()?, Some(MacroSubNs::Attr))1869        .map(|it| it.def)1870        .map(Into::into)1871}18721873fn resolve_hir_path_<'db>(1874    db: &'db dyn HirDatabase,1875    resolver: &Resolver<'db>,1876    infer_body: Option<InferBodyId<'db>>,1877    path: &Path,1878    prefer_value_ns: bool,1879    hygiene: HygieneId,1880    store: Option<&ExpressionStore>,1881    resolve_per_ns: bool,1882) -> PathResolutionPerNs<'db> {1883    let types = || {1884        let (ty, unresolved, ty_is_visible) = match path.type_anchor() {1885            Some(type_ref) => resolver.generic_def().and_then(|def| {1886                let generics = OnceCell::new();1887                let (_, res) = TyLoweringContext::new(1888                    db,1889                    resolver,1890                    store?,1891                    resolver.expression_store_owner().unwrap_or_else(|| def.into()),1892                    def,1893                    &generics,1894                    LifetimeElisionKind::Infer,1895                    LifetimeLoweringMode::LateParam,1896                )1897                .with_interning_mode(LoweringMode::Ide)1898                .lower_ty_ext(type_ref);1899                res.map(|ty_ns| (ty_ns, path.segments().first(), Visibility::Public))1900            }),1901            None => {1902                let (ty, remaining_idx, _, _, vis) =1903                    resolver.resolve_path_in_type_ns_with_prefix_info(db, path)?;1904                match remaining_idx {1905                    Some(remaining_idx) => {1906                        if remaining_idx + 1 == path.segments().len() {1907                            Some((ty, path.segments().last(), vis))1908                        } else {1909                            None1910                        }1911                    }1912                    None => Some((ty, None, vis)),1913                }1914            }1915        }?;19161917        // If we are in a TypeNs for a Trait, and we have an unresolved name, try to resolve it as a type1918        // within the trait's associated types.1919        if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty)1920            && let Some(type_alias_id) =1921                trait_id.trait_items(db).associated_type_by_name(unresolved.name)1922        {1923            return Some((1924                PathResolution::Def(ModuleDefId::from(type_alias_id).into()),1925                ty_is_visible,1926            ));1927        }19281929        let res = match ty {1930            TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),1931            TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()),1932            TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {1933                PathResolution::Def(Adt::from(it).into())1934            }1935            TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),1936            TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),1937            TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),1938            TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),1939            TypeNs::ModuleId(it) => PathResolution::Def(ModuleDef::Module(it.into())),1940        };1941        match unresolved {1942            Some(unresolved) => resolver1943                .generic_def()1944                .and_then(|def| {1945                    hir_ty::associated_type_shorthand_candidates(1946                        db,1947                        def,1948                        res.in_type_ns()?,1949                        |name, _| name == unresolved.name,1950                    )1951                })1952                .map(TypeAlias::from)1953                .map(Into::into)1954                .map(|def| (PathResolution::Def(def), ty_is_visible)),1955            None => Some((res, ty_is_visible)),1956        }1957    };19581959    let body_owner = resolver.expression_store_owner();1960    let values = || resolve_hir_value_path(db, resolver, body_owner, infer_body, path, hygiene);19611962    let items = || {1963        resolver1964            .resolve_module_path_in_items(db, path.mod_path()?)1965            .take_types_full()1966            .map(|it| (PathResolution::Def(it.def.into()), it.vis))1967    };19681969    let macros = || {1970        resolver1971            .resolve_path_as_macro(db, path.mod_path()?, None)1972            .map(|res| (PathResolution::Def(ModuleDef::Macro(res.def.into())), res.vis))1973    };19741975    let mut types_ns: Option<Option<_>> = None;1976    let mut values_ns: Option<Option<_>> = None;19771978    let mut types_is_visible: Option<bool> = None;1979    let mut values_is_visible: Option<bool> = None;19801981    if !resolve_per_ns {1982        if prefer_value_ns {1983            values_ns = Some(values().inspect(|(_, vis)| {1984                values_is_visible = Some(resolver.is_visible(db, *vis));1985            }));19861987            if let Some(Some((res, _))) = values_ns1988                && values_is_visible.unwrap_or_default()1989            {1990                return PathResolutionPerNs::new(None, Some(res), None);1991            }1992        } else {1993            types_ns = Some(types().or_else(items).inspect(|(_, vis)| {1994                types_is_visible = Some(resolver.is_visible(db, *vis));1995            }));19961997            if let Some(Some((res, _))) = types_ns1998                && types_is_visible.unwrap_or_default()1999            {2000                return PathResolutionPerNs::new(Some(res), None, None);

Code quality findings 19

Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
&& let Expr::Block { tail: Some(tail), .. } = store[expr_id]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
ExprOrPatId::ExprId(idx) => match &store[idx] {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
ExprOrPatId::PatId(idx) => match &store[idx] {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
field_types[field].ty().instantiate(interner, subst).skip_norm_wip(),
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?;
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
record_literal_matched_fields(db, infer, expr_id, &body[expr_id])?;
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
record_pattern_matched_fields(db, infer, pat_id, &body[pat_id])?;
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
let ty = field_types[local_id].ty().instantiate(interner, substs).skip_norm_wip();
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
let into_future_type = items.into_iter().find_map(|item| match item {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match self.resolver.resolve_path_in_value_ns_fully(
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
let path = match expr_or_pat_id {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
ExprOrPatId::ExprId(idx) => match &store[idx] {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
ExprOrPatId::PatId(idx) => match &store[idx] {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match res {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
|it| match it {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
let (fields, _spread) = match expr {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
let (fields, _ellipsis) = match pat {

Get this view in your editor

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

Generated by searchcode.com · powered by code_get_file + code_get_findings