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