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