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