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