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