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);