1use std::{
9 cell::OnceCell,
10 iter::{self, once},
11};
12
13use either::Either;
14use hir_def::{
15 AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, ExpressionStoreOwnerId, FieldId,
16 FunctionId, GenericDefId, HasModule, LocalFieldId, 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_ide::{
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};
64
65use 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};
73
74#[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}
84
85#[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}
108
109impl<'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 }
118
119 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 }
127
128 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 }
159
160 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 }
169
170 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 }
179
180 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 None
215 };
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 }
224
225 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 None
260 };
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 }
274
275 pub(crate) fn new_for_resolver(
276 resolver: Resolver<'db>,
277 node: InFile<&SyntaxNode>,
278 ) -> SourceAnalyzer<'db> {
279 SourceAnalyzer {
280 type_owner: resolver
281 .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 }
290
291 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 }
298
299 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 }
306
307 pub(crate) fn ty(&self, ty: Ty<'db>) -> Type<'db> {
308 Type { owner: self.type_owner, ty: EarlyBinder::bind(ty) }
309 }
310
311 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 }
331
332 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 }
339
340 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 }
347
348 fn param_and<'a>(&self, param_env: ParamEnv<'a>) -> ParamEnvAndCrate<'a> {
349 ParamEnvAndCrate { param_env, krate: self.resolver.krate() }
350 }
351
352 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 }
366
367 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 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 }
393
394 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 }
416
417 PredicateEvaluationResult::holds("predicate holds")
418 }
419
420 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 }
424
425 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 }
429
430 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 }
434
435 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 }
439
440 pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment]> {
441 let expr_id = self.expr_id(expr.clone())?.as_expr()?;
444 let infer = self.infer()?;
445 infer.expr_adjustment(expr_id)
446 }
447
448 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);
454
455 let type_ref = self.type_id(ty)?;
456
457 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 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);
476
477 struct VarsCtx<'a, 'db> {
478 types: &'a DefaultAny<'db>,
479 infer: Option<&'a InferenceResult<'db>>,
480 }
481
482 impl<'db> TyLoweringInferVarsCtx<'db> for VarsCtx<'_, 'db> {
483 fn next_ty_var(&mut self, span: hir_ide::Span) -> Ty<'db> {
484 if let hir_ide::Span::TypeRefId(type_ref) = span
485 && let Some(ty) =
486 self.infer.and_then(|infer| infer.type_of_type_placeholder(type_ref))
487 {
488 ty
489 } else {
490 self.types.types.error
491 }
492 }
493 fn next_const_var(&mut self, _span: hir_ide::Span) -> hir_ide::next_solver::Const<'db> {
494 self.types.consts.error
495 }
496 fn next_region_var(&mut self, _span: hir_ide::Span) -> Region<'db> {
497 self.types.regions.error
498 }
499 }
500
501 Some(self.ty(ty))
502 }
503
504 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 }
514
515 fn expr_id_is_diverging(
516 &self,
517 store: &ExpressionStore,
518 infer: &InferenceResult<'_>,
519 expr_id: ExprOrPatId,
520 ) -> bool {
521 if infer.type_of_expr_or_pat(expr_id).is_some_and(|ty| ty.is_never()) {
523 true
524 } else if let ExprOrPatId::ExprId(expr_id) = expr_id
525 && let Expr::Block { tail: Some(tail), .. } = store[expr_id]
526 {
527 self.expr_id_is_diverging(store, infer, tail.into())
528 } else {
529 false
530 }
531 }
532
533 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_id
541 .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 }
548
549 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) => infer
558 .expr_adjustment(idx)
559 .and_then(|adjusts| adjusts.last())
560 .map(|adjust| adjust.target.as_ref()),
561 ExprOrPatId::PatId(idx) => infer
562 .pat_adjustment(idx)
563 .and_then(|adjusts| adjusts.last())
564 .map(|adjust| adjust.source.as_ref()),
565 };
566
567 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 }
571
572 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 }
583
584 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 }
596
597 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_ide::BindingMode(hir_ide::ByRef::No, _) => BindingMode::Move,
606 hir_ide::BindingMode(hir_ide::ByRef::Yes(hir_ide::next_solver::Mutability::Mut), _) => {
607 BindingMode::Ref(Mutability::Mut)
608 }
609 hir_ide::BindingMode(hir_ide::ByRef::Yes(hir_ide::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 infer
623 .pat_adjustment(pat_id.as_pat()?)?
624 .iter()
625 .map(|adjust| self.ty(adjust.source.as_ref()))
626 .collect(),
627 )
628 }
629
630 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 }
644
645 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)?;
652
653 Some(self.resolve_impl_method_or_trait_def(db, f_in_trait, substs))
654 }
655
656 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 }
679
680 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 }
688
689 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 }
699
700 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 None
712 }
713
714 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 }
744
745 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 }
757
758 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 }
770
771 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.RangeFromCopy
786 } else {
787 lang_items.RangeFrom
788 }
789 }
790 (RangeOp::Exclusive, true, true) => {
791 if has_new_range {
792 lang_items.RangeCopy
793 } else {
794 lang_items.Range
795 }
796 }
797 (RangeOp::Inclusive, false, true) => {
798 if has_new_range {
799 lang_items.RangeToInclusiveCopy
800 } else {
801 lang_items.RangeToInclusive
802 }
803 }
804 (RangeOp::Inclusive, true, true) => {
805 if has_new_range {
806 lang_items.RangeInclusiveCopy
807 } else {
808 lang_items.RangeInclusiveStruct
809 }
810 }
811 (RangeOp::Inclusive, false, false) => None,
813 (RangeOp::Inclusive, true, false) => None,
814 }
815 }
816
817 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()?)?;
823
824 let into_future_trait = self
825 .resolver
826 .resolve_known_trait(db, &path![core::future::IntoFuture])
827 .map(Trait::from);
828
829 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 }
845
846 let poll_fn = self.lang_items(db).FuturePoll?;
847 let substs = GenericArgs::new_from_slice(&[ty.into()]);
850 Some(self.resolve_impl_method_or_trait_def(db, poll_fn, substs))
851 }
852
853 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 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 };
878
879 let ty = self.ty_of_expr(prefix_expr.expr()?)?;
880
881 let substs = GenericArgs::new_from_slice(&[ty.into()]);
884
885 Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
886 }
887
888 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);
896
897 let (_index_trait, index_fn) = (lang_items.Index?, lang_items.Index_index?);
898 let op_fn = self
899 .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 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 }
913
914 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()?)?;
922
923 let (op_fn, _op_trait) = lang_items_for_bin_op(self.lang_items(db), op)
924 .and_then(|(method, trait_)| method.zip(trait_))?;
925 let substs = GenericArgs::new_from_slice(&[lhs.into(), rhs.into()]);
928
929 Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
930 }
931
932 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()?)?;
938
939 let op_fn = self.lang_items(db).TryTraitBranch?;
940 let substs = GenericArgs::new_from_slice(&[ty.into()]);
943
944 Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
945 }
946
947 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);
956
957 let ast_name = field.field_name()?;
958 let local_name = ast_name.as_name();
959 let local = if field.name_ref().is_some() {
960 None
961 } else {
962 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 }
995
996 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 }
1019
1020 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()?;
1029
1030 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 }
1041
1042 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()?;
1049
1050 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 };
1060
1061 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 }
1075
1076 pub(crate) fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option<crate::TypeParam> {
1077 let name = name.as_name();
1078 self.resolver
1079 .all_generic_params()
1080 .find_map(|(params, parent)| params.find_type_by_name(&name, parent))
1081 .map(crate::TypeParam::from)
1082 }
1083
1084 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)?;
1092
1093 let env = self.trait_environment(db);
1094
1095 let interner = DbInterner::new_with(db, env.krate);
1096 let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
1097
1098 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 };
1146
1147 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 None
1156 }
1157
1158 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();
1165
1166 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) = self
1186 .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 };
1214
1215 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 None
1279 })();
1280 if resolved.is_some() {
1281 return resolved;
1282 }
1283
1284 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 = path
1290 .parent_path()
1291 .and_then(|p| collector.lower_path(p, &mut ExprCollector::impl_trait_error_allocator));
1292 let (store, _) = collector.store.finish();
1293
1294 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 }
1302
1303 let meta_path = path
1304 .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);
1312
1313 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() => path
1318 .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 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 module
1343 .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 res => res.map(|it| (it, None)),
1356 };
1357 } else if let Some(meta_path) = meta_path {
1358 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 }
1366
1367 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) = self
1380 .resolver
1381 .def_map()
1382 .derive_helpers_in_scope(InFile::new(self.file_id, ast_id))
1383 {
1384 let name_ref = name_ref.as_name();
1386 for (macro_id, mut helpers) in
1387 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 None => path
1409 .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 resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store).map(|it| (it, None))
1421 } else {
1422 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 return None;
1479 }
1480 Some(subst)
1481 })();
1482 Some((res, subst))
1483 }
1484 }
1485
1486 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 }
1507
1508 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()?;
1515
1516 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 }
1523
1524 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()?;
1531
1532 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])?;
1536
1537 let res = self.missing_fields(db, substs, variant, matched_fields);
1538 Some(res)
1539 }
1540
1541 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()?;
1548
1549 let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;
1550 let substs = infer.pat_ty(pat_id).as_adt()?.1;
1551
1552 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 }
1557
1558 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()?;
1565
1566 let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;
1567 let substs = infer.pat_ty(pat_id).as_adt()?.1;
1568
1569 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 }
1574
1575 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);
1584
1585 missing_fields
1586 .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 }
1594
1595 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 }
1600
1601 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::No
1613 })
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 false
1622 }
1623
1624 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 }
1650
1651 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 }
1666
1667 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 }
1691
1692 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 }
1699
1700 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).0
1707 }
1708
1709 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 }
1728
1729 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 }
1744
1745 fn lang_items<'a>(&self, db: &'a dyn HirDatabase) -> &'a LangItems {
1746 hir_def::lang_item::lang_items(db, self.resolver.krate())
1747 }
1748
1749 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}
1753
1754fn 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}
1774
1775fn 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 scopes
1783 .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 }
1790
1791 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 .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}
1808
1809fn 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 = scopes
1820 .scope_by_expr()
1821 .iter()
1822 .filter_map(|(id, scope)| {
1823 let source = source_map.expr_syntax(id).ok()?;
1824 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_range
1834 });
1835
1836 child_scopes
1837 .max_by(|&(r1, _, _), &(r2, _, _)| {
1838 if r1.contains_range(r2) {
1839 std::cmp::Ordering::Greater
1840 } else if r2.contains_range(r1) {
1841 std::cmp::Ordering::Less
1842 } else {
1843 r1.start().cmp(&r2.start())
1844 }
1845 })
1846 .map(|(_ptr, scope, expr)| (*scope, expr))
1847}
1848
1849#[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}
1860
1861#[inline]
1862pub(crate) fn resolve_hir_path_as_attr_macro(
1863 db: &dyn HirDatabase,
1864 resolver: &Resolver<'_>,
1865 path: &Path,
1866) -> Option<Macro> {
1867 resolver
1868 .resolve_path_as_macro(db, path.mod_path()?, Some(MacroSubNs::Attr))
1869 .map(|it| it.def)
1870 .map(Into::into)
1871}
1872
1873fn 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 None
1910 }
1911 }
1912 None => Some((ty, None, vis)),
1913 }
1914 }
1915 }?;
1916
1917 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 }
1928
1929 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) => resolver
1943 .generic_def()
1944 .and_then(|def| {
1945 hir_ide::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 };
1958
1959 let body_owner = resolver.expression_store_owner();
1960 let values = || resolve_hir_value_path(db, resolver, body_owner, infer_body, path, hygiene);
1961
1962 let items = || {
1963 resolver
1964 .resolve_module_path_in_items(db, path.mod_path()?)
1965 .take_types_full()
1966 .map(|it| (PathResolution::Def(it.def.into()), it.vis))
1967 };
1968
1969 let macros = || {
1970 resolver
1971 .resolve_path_as_macro(db, path.mod_path()?, None)
1972 .map(|res| (PathResolution::Def(ModuleDef::Macro(res.def.into())), res.vis))
1973 };
1974
1975 let mut types_ns: Option<Option<_>> = None;
1976 let mut values_ns: Option<Option<_>> = None;
1977
1978 let mut types_is_visible: Option<bool> = None;
1979 let mut values_is_visible: Option<bool> = None;
1980
1981 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 }));
1986
1987 if let Some(Some((res, _))) = values_ns
1988 && 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 }));
1996
1997 if let Some(Some((res, _))) = types_ns
1998 && types_is_visible.unwrap_or_default()
1999 {
2000 return PathResolutionPerNs::new(Some(res), None, None);
2001 }
2002 }
2003 }
2004
2005 let mut macros_is_visible = false;
2006
2007 let mut types = types_ns.unwrap_or_else(|| types().or_else(items)).map(|(res, vis)| {
2008 types_is_visible = Some(types_is_visible.unwrap_or_else(|| resolver.is_visible(db, vis)));
2009 res
2010 });
2011 let mut values = values_ns.unwrap_or_else(values).map(|(res, vis)| {
2012 values_is_visible = Some(values_is_visible.unwrap_or_else(|| resolver.is_visible(db, vis)));
2013 res
2014 });
2015 let mut macros = macros().map(|(res, vis)| {
2016 macros_is_visible = resolver.is_visible(db, vis);
2017 res
2018 });
2019
2020 let types_is_visible = types_is_visible.unwrap_or_default();
2021 let values_is_visible = values_is_visible.unwrap_or_default();
2022
2023 if types_is_visible || values_is_visible || macros_is_visible {
2026 if !types_is_visible {
2027 types = None;
2028 }
2029 if !values_is_visible {
2030 values = None;
2031 }
2032 if !macros_is_visible {
2033 macros = None;
2034 }
2035 }
2036
2037 PathResolutionPerNs { type_ns: types, value_ns: values, macro_ns: macros }
2038}
2039
2040fn resolve_hir_value_path<'db>(
2041 db: &'db dyn HirDatabase,
2042 resolver: &Resolver<'db>,
2043 store_owner: Option<ExpressionStoreOwnerId>,
2044 infer_body: Option<InferBodyId<'db>>,
2045 path: &Path,
2046 hygiene: HygieneId,
2047) -> Option<(PathResolution<'db>, Visibility)> {
2048 resolver.resolve_path_in_value_ns_with_prefix_info(db, path, hygiene).and_then(
2049 |(val, _, vis)| {
2050 let ResolveValueResult::ValueNs(val) = val else { return None };
2051 let res = match val {
2052 ValueNs::LocalBinding(binding_id) => {
2053 let var = Local { parent: store_owner?, parent_infer: infer_body?, binding_id };
2054 PathResolution::Local(var)
2055 }
2056 ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()),
2057 ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()),
2058 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
2059 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
2060 ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
2061 ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
2062 ValueNs::GenericParam(id) => PathResolution::ConstParam(id.into()),
2063 };
2064 Some((res, vis))
2065 },
2066 )
2067}
2068
2069fn resolve_hir_path_qualifier<'db>(
2083 db: &'db dyn HirDatabase,
2084 resolver: &Resolver<'db>,
2085 path: &Path,
2086 store: &ExpressionStore,
2087) -> Option<PathResolution<'db>> {
2088 (|| {
2089 let (ty, unresolved) = match path.type_anchor() {
2090 Some(type_ref) => resolver.generic_def().and_then(|def| {
2091 let generics = OnceCell::new();
2092 let (_, res) = TyLoweringContext::new(
2093 db,
2094 resolver,
2095 store,
2096 resolver.expression_store_owner().unwrap_or_else(|| def.into()),
2097 def,
2098 &generics,
2099 LifetimeElisionKind::Infer,
2100 LifetimeLoweringMode::LateParam,
2101 )
2102 .with_interning_mode(LoweringMode::Ide)
2103 .lower_ty_ext(type_ref);
2104 res.map(|ty_ns| (ty_ns, path.segments().first()))
2105 }),
2106 None => {
2107 let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db, path)?;
2108 match remaining_idx {
2109 Some(remaining_idx) => {
2110 if remaining_idx + 1 == path.segments().len() {
2111 Some((ty, path.segments().last()))
2112 } else {
2113 None
2114 }
2115 }
2116 None => Some((ty, None)),
2117 }
2118 }
2119 }?;
2120
2121 if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty)
2124 && let Some(type_alias_id) =
2125 trait_id.trait_items(db).associated_type_by_name(unresolved.name)
2126 {
2127 return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
2128 }
2129
2130 let res = match ty {
2131 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
2132 TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()),
2133 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
2134 PathResolution::Def(Adt::from(it).into())
2135 }
2136 TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
2137 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
2138 TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
2139 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
2140 TypeNs::ModuleId(it) => PathResolution::Def(ModuleDef::Module(it.into())),
2141 };
2142 match unresolved {
2143 Some(unresolved) => resolver
2144 .generic_def()
2145 .and_then(|def| {
2146 hir_ide::associated_type_shorthand_candidates(
2147 db,
2148 def,
2149 res.in_type_ns()?,
2150 |name, _| name == unresolved.name,
2151 )
2152 })
2153 .map(TypeAlias::from)
2154 .map(Into::into)
2155 .map(PathResolution::Def),
2156 None => Some(res),
2157 }
2158 })()
2159 .or_else(|| {
2160 resolver
2161 .resolve_module_path_in_items(db, path.mod_path()?)
2162 .take_types()
2163 .map(|it| PathResolution::Def(it.into()))
2164 })
2165}
2166
2167pub(crate) fn name_hygiene(db: &dyn HirDatabase, name: InFile<&SyntaxNode>) -> HygieneId {
2168 let Some(macro_file) = name.file_id.macro_file() else {
2169 return HygieneId::ROOT;
2170 };
2171 let span_map = macro_file.expansion_span_map(db);
2172 let ctx = span_map.span_at(name.value.text_range().start()).ctx;
2173 HygieneId::new(ctx.opaque_and_semiopaque(db))
2174}
2175
2176fn record_literal_matched_fields(
2177 db: &dyn HirDatabase,
2178 infer: &InferenceResult<'_>,
2179 id: ExprId,
2180 expr: &Expr,
2181) -> Option<(VariantId, Vec<LocalFieldId>)> {
2182 let (fields, _spread) = match expr {
2183 Expr::RecordLit { fields, spread, .. } => (fields, spread),
2184 _ => return None,
2185 };
2186
2187 let variant_def = infer.variant_resolution_for_expr(id)?;
2188 if let VariantId::UnionId(_) = variant_def {
2189 return None;
2190 }
2191
2192 let variant_data = variant_def.fields(db);
2193
2194 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
2195 let matched_fields: Vec<LocalFieldId> = variant_data
2198 .fields()
2199 .iter()
2200 .filter_map(|(f, d)| (!specified_fields.contains(&d.name)).then_some(f))
2201 .collect();
2202 if matched_fields.is_empty() {
2203 return None;
2204 }
2205 Some((variant_def, matched_fields))
2206}
2207
2208fn record_pattern_matched_fields(
2209 db: &dyn HirDatabase,
2210 infer: &InferenceResult<'_>,
2211 id: PatId,
2212 pat: &Pat,
2213) -> Option<(VariantId, Vec<LocalFieldId>)> {
2214 let (fields, _ellipsis) = match pat {
2215 Pat::Record { path: _, args, ellipsis } => (args, *ellipsis),
2216 _ => return None,
2217 };
2218
2219 let variant_def = infer.variant_resolution_for_pat(id)?;
2220 if let VariantId::UnionId(_) = variant_def {
2221 return None;
2222 }
2223
2224 let variant_data = variant_def.fields(db);
2225
2226 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
2227 let matched_fields: Vec<LocalFieldId> = variant_data
2230 .fields()
2231 .iter()
2232 .filter_map(|(f, d)| if !specified_fields.contains(&d.name) { Some(f) } else { None })
2233 .collect();
2234 if matched_fields.is_empty() {
2235 return None;
2236 }
2237 Some((variant_def, matched_fields))
2238}