1use std::iter::{self, once};
9
10use either::Either;
11use hir_def::{
12 AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId,
13 LocalFieldId, ModuleDefId, StructId, TraitId, VariantId,
14 expr_store::{
15 Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, HygieneId,
16 lower::ExprCollector,
17 path::Path,
18 scope::{ExprScopes, ScopeId},
19 },
20 hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat},
21 lang_item::LangItems,
22 nameres::MacroSubNs,
23 resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope},
24 type_ref::{Mutability, TypeRef, TypeRefId},
25};
26use hir_expand::{
27 HirFileId, InFile,
28 mod_path::{ModPath, PathKind, path},
29 name::{AsName, Name},
30};
31use hir_ty::{
32 Adjustment, InferenceResult, LifetimeElisionKind, ParamEnvAndCrate, TyLoweringContext,
33 diagnostics::{
34 InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields,
35 unsafe_operations,
36 },
37 lang_items::lang_items_for_bin_op,
38 method_resolution::{self, CandidateId},
39 next_solver::{
40 DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, Ty, TyKind, TypingMode,
41 infer::DbInternerInferExt,
42 },
43 traits::structurally_normalize_ty,
44};
45use intern::sym;
46use itertools::Itertools;
47use rustc_type_ir::{
48 AliasTyKind,
49 inherent::{AdtDef, IntoKind, Ty as _},
50};
51use smallvec::SmallVec;
52use stdx::never;
53use syntax::{
54 SyntaxKind, SyntaxNode, TextRange, TextSize,
55 ast::{self, AstNode, RangeItem, RangeOp},
56};
57use triomphe::Arc;
58
59use crate::{
60 Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field,
61 Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct, ToolModule, Trait,
62 TupleField, Type, TypeAlias, Variant,
63 db::HirDatabase,
64 semantics::{PathResolution, PathResolutionPerNs},
65};
66
67#[derive(Debug)]
70pub(crate) struct SourceAnalyzer<'db> {
71 pub(crate) file_id: HirFileId,
72 pub(crate) resolver: Resolver<'db>,
73 pub(crate) body_or_sig: Option<BodyOrSig<'db>>,
74}
75
76#[derive(Debug)]
77pub(crate) enum BodyOrSig<'db> {
78 Body {
79 def: DefWithBodyId,
80 body: Arc<Body>,
81 source_map: Arc<BodySourceMap>,
82 infer: Option<&'db InferenceResult<'db>>,
83 },
84 VariantFields {
86 def: VariantId,
87 store: Arc<ExpressionStore>,
88 source_map: Arc<ExpressionStoreSourceMap>,
89 },
90 Sig {
91 def: GenericDefId,
92 store: Arc<ExpressionStore>,
93 source_map: Arc<ExpressionStoreSourceMap>,
94 },
96}
97
98impl<'db> SourceAnalyzer<'db> {
99 pub(crate) fn new_for_body(
100 db: &'db dyn HirDatabase,
101 def: DefWithBodyId,
102 node: InFile<&SyntaxNode>,
103 offset: Option<TextSize>,
104 ) -> SourceAnalyzer<'db> {
105 Self::new_for_body_(db, def, node, offset, Some(InferenceResult::for_body(db, def)))
106 }
107
108 pub(crate) fn new_for_body_no_infer(
109 db: &'db dyn HirDatabase,
110 def: DefWithBodyId,
111 node: InFile<&SyntaxNode>,
112 offset: Option<TextSize>,
113 ) -> SourceAnalyzer<'db> {
114 Self::new_for_body_(db, def, node, offset, None)
115 }
116
117 pub(crate) fn new_for_body_(
118 db: &'db dyn HirDatabase,
119 def: DefWithBodyId,
120 node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
121 offset: Option<TextSize>,
122 infer: Option<&'db InferenceResult<'db>>,
123 ) -> SourceAnalyzer<'db> {
124 let (body, source_map) = db.body_with_source_map(def);
125 let scopes = db.expr_scopes(def);
126 let scope = match offset {
127 None => scope_for(db, &scopes, &source_map, node),
128 Some(offset) => {
129 debug_assert!(
130 node.text_range().contains_inclusive(offset),
131 "{:?} not in {:?}",
132 offset,
133 node.text_range()
134 );
135 scope_for_offset(db, &scopes, &source_map, node.file_id, offset)
136 }
137 };
138 let resolver = resolver_for_scope(db, def, scope);
139 SourceAnalyzer {
140 resolver,
141 body_or_sig: Some(BodyOrSig::Body { def, body, source_map, infer }),
142 file_id,
143 }
144 }
145
146 pub(crate) fn new_generic_def(
147 db: &'db dyn HirDatabase,
148 def: GenericDefId,
149 InFile { file_id, .. }: InFile<&SyntaxNode>,
150 _offset: Option<TextSize>,
151 ) -> SourceAnalyzer<'db> {
152 let (_params, store, source_map) = db.generic_params_and_store_and_source_map(def);
153 let resolver = def.resolver(db);
154 SourceAnalyzer {
155 resolver,
156 body_or_sig: Some(BodyOrSig::Sig { def, store, source_map }),
157 file_id,
158 }
159 }
160
161 pub(crate) fn new_variant_body(
162 db: &'db dyn HirDatabase,
163 def: VariantId,
164 InFile { file_id, .. }: InFile<&SyntaxNode>,
165 _offset: Option<TextSize>,
166 ) -> SourceAnalyzer<'db> {
167 let (fields, source_map) = def.fields_with_source_map(db);
168 let resolver = def.resolver(db);
169 SourceAnalyzer {
170 resolver,
171 body_or_sig: Some(BodyOrSig::VariantFields {
172 def,
173 store: fields.store.clone(),
174 source_map: source_map.clone(),
175 }),
176 file_id,
177 }
178 }
179
180 pub(crate) fn new_for_resolver(
181 resolver: Resolver<'db>,
182 node: InFile<&SyntaxNode>,
183 ) -> SourceAnalyzer<'db> {
184 SourceAnalyzer { resolver, body_or_sig: None, file_id: node.file_id }
185 }
186
187 fn body_(
189 &self,
190 ) -> Option<(DefWithBodyId, &Body, &BodySourceMap, Option<&InferenceResult<'db>>)> {
191 self.body_or_sig.as_ref().and_then(|it| match it {
192 BodyOrSig::Body { def, body, source_map, infer } => {
193 Some((*def, &**body, &**source_map, infer.as_deref()))
194 }
195 _ => None,
196 })
197 }
198
199 fn infer(&self) -> Option<&InferenceResult<'db>> {
200 self.body_or_sig.as_ref().and_then(|it| match it {
201 BodyOrSig::Sig { .. } => None,
202 BodyOrSig::VariantFields { .. } => None,
203 BodyOrSig::Body { infer, .. } => infer.as_deref(),
204 })
205 }
206
207 fn body(&self) -> Option<&Body> {
208 self.body_or_sig.as_ref().and_then(|it| match it {
209 BodyOrSig::Sig { .. } => None,
210 BodyOrSig::VariantFields { .. } => None,
211 BodyOrSig::Body { body, .. } => Some(&**body),
212 })
213 }
214
215 pub(crate) fn store(&self) -> Option<&ExpressionStore> {
216 self.body_or_sig.as_ref().map(|it| match it {
217 BodyOrSig::Sig { store, .. } => &**store,
218 BodyOrSig::VariantFields { store, .. } => &**store,
219 BodyOrSig::Body { body, .. } => &body.store,
220 })
221 }
222
223 pub(crate) fn store_sm(&self) -> Option<&ExpressionStoreSourceMap> {
224 self.body_or_sig.as_ref().map(|it| match it {
225 BodyOrSig::Sig { source_map, .. } => &**source_map,
226 BodyOrSig::VariantFields { source_map, .. } => &**source_map,
227 BodyOrSig::Body { source_map, .. } => &source_map.store,
228 })
229 }
230
231 fn param_and<'a>(&self, param_env: ParamEnv<'a>) -> ParamEnvAndCrate<'a> {
232 ParamEnvAndCrate { param_env, krate: self.resolver.krate() }
233 }
234
235 fn trait_environment(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> {
236 self.param_and(
237 self.body_()
238 .map(|(def, ..)| def)
239 .map_or_else(ParamEnv::empty, |def| db.trait_environment_for_body(def)),
240 )
241 }
242
243 pub(crate) fn expr_id(&self, expr: ast::Expr) -> Option<ExprOrPatId> {
244 let src = InFile { file_id: self.file_id, value: expr };
245 self.store_sm()?.node_expr(src.as_ref())
246 }
247
248 fn pat_id(&self, pat: &ast::Pat) -> Option<ExprOrPatId> {
249 let src = InFile { file_id: self.file_id, value: pat };
250 self.store_sm()?.node_pat(src)
251 }
252
253 fn type_id(&self, pat: &ast::Type) -> Option<TypeRefId> {
254 let src = InFile { file_id: self.file_id, value: pat };
255 self.store_sm()?.node_type(src)
256 }
257
258 fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingId> {
259 let pat_id = self.pat_id(&pat.clone().into())?;
260 if let Pat::Bind { id, .. } = self.store()?[pat_id.as_pat()?] { Some(id) } else { None }
261 }
262
263 pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment<'db>]> {
264 let expr_id = self.expr_id(expr.clone())?.as_expr()?;
267 let infer = self.infer()?;
268 infer.expr_adjustment(expr_id)
269 }
270
271 pub(crate) fn type_of_type(
272 &self,
273 db: &'db dyn HirDatabase,
274 ty: &ast::Type,
275 ) -> Option<Type<'db>> {
276 let interner = DbInterner::new_no_crate(db);
277
278 let type_ref = self.type_id(ty)?;
279
280 let mut ty = TyLoweringContext::new(
281 db,
282 &self.resolver,
283 self.store()?,
284 self.resolver.generic_def()?,
285 LifetimeElisionKind::Infer,
289 )
290 .lower_ty(type_ref);
291
292 if let Some(infer) = self.infer()
294 && let Some(store) = self.store()
295 {
296 let mut inferred_types = vec![];
297 TypeRef::walk(type_ref, store, &mut |type_ref_id, type_ref| {
298 if matches!(type_ref, TypeRef::Placeholder) {
299 inferred_types.push(infer.type_of_type_placeholder(type_ref_id));
300 }
301 });
302 let mut inferred_types = inferred_types.into_iter();
303
304 let substituted_ty = hir_ty::next_solver::fold::fold_tys(interner, ty, |ty| {
305 if ty.is_ty_error() { inferred_types.next().flatten().unwrap_or(ty) } else { ty }
306 });
307
308 let success =
310 inferred_types.next().is_none() && !substituted_ty.references_non_lt_error();
311 if success {
312 ty = substituted_ty;
313 }
314 }
315
316 Some(Type::new_with_resolver(db, &self.resolver, ty))
317 }
318
319 pub(crate) fn type_of_expr(
320 &self,
321 db: &'db dyn HirDatabase,
322 expr: &ast::Expr,
323 ) -> Option<(Type<'db>, Option<Type<'db>>)> {
324 let expr_id = self.expr_id(expr.clone())?;
325 let infer = self.infer()?;
326 let coerced = expr_id
327 .as_expr()
328 .and_then(|expr_id| infer.expr_adjustment(expr_id))
329 .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target));
330 let ty = infer[expr_id];
331 let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty);
332 Some((mk_ty(ty), coerced.map(mk_ty)))
333 }
334
335 pub(crate) fn type_of_pat(
336 &self,
337 db: &'db dyn HirDatabase,
338 pat: &ast::Pat,
339 ) -> Option<(Type<'db>, Option<Type<'db>>)> {
340 let expr_or_pat_id = self.pat_id(pat)?;
341 let infer = self.infer()?;
342 let coerced = match expr_or_pat_id {
343 ExprOrPatId::ExprId(idx) => infer
344 .expr_adjustment(idx)
345 .and_then(|adjusts| adjusts.last().cloned())
346 .map(|adjust| adjust.target),
347 ExprOrPatId::PatId(idx) => {
348 infer.pat_adjustment(idx).and_then(|adjusts| adjusts.last().cloned())
349 }
350 };
351
352 let ty = infer[expr_or_pat_id];
353 let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty);
354 Some((mk_ty(ty), coerced.map(mk_ty)))
355 }
356
357 pub(crate) fn type_of_binding_in_pat(
358 &self,
359 db: &'db dyn HirDatabase,
360 pat: &ast::IdentPat,
361 ) -> Option<Type<'db>> {
362 let binding_id = self.binding_id_of_pat(pat)?;
363 let infer = self.infer()?;
364 let ty = infer[binding_id];
365 let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty);
366 Some(mk_ty(ty))
367 }
368
369 pub(crate) fn type_of_self(
370 &self,
371 db: &'db dyn HirDatabase,
372 _param: &ast::SelfParam,
373 ) -> Option<Type<'db>> {
374 let binding = self.body()?.self_param?;
375 let ty = self.infer()?[binding];
376 Some(Type::new_with_resolver(db, &self.resolver, ty))
377 }
378
379 pub(crate) fn binding_mode_of_pat(
380 &self,
381 _db: &'db dyn HirDatabase,
382 pat: &ast::IdentPat,
383 ) -> Option<BindingMode> {
384 let id = self.pat_id(&pat.clone().into())?;
385 let infer = self.infer()?;
386 infer.binding_mode(id.as_pat()?).map(|bm| match bm {
387 hir_ty::BindingMode::Move => BindingMode::Move,
388 hir_ty::BindingMode::Ref(hir_ty::next_solver::Mutability::Mut) => {
389 BindingMode::Ref(Mutability::Mut)
390 }
391 hir_ty::BindingMode::Ref(hir_ty::next_solver::Mutability::Not) => {
392 BindingMode::Ref(Mutability::Shared)
393 }
394 })
395 }
396 pub(crate) fn pattern_adjustments(
397 &self,
398 db: &'db dyn HirDatabase,
399 pat: &ast::Pat,
400 ) -> Option<SmallVec<[Type<'db>; 1]>> {
401 let pat_id = self.pat_id(pat)?;
402 let infer = self.infer()?;
403 Some(
404 infer
405 .pat_adjustment(pat_id.as_pat()?)?
406 .iter()
407 .map(|ty| Type::new_with_resolver(db, &self.resolver, *ty))
408 .collect(),
409 )
410 }
411
412 pub(crate) fn resolve_method_call_as_callable(
413 &self,
414 db: &'db dyn HirDatabase,
415 call: &ast::MethodCallExpr,
416 ) -> Option<Callable<'db>> {
417 let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
418 let (func, args) = self.infer()?.method_resolution(expr_id)?;
419 let interner = DbInterner::new_no_crate(db);
420 let ty = db.value_ty(func.into())?.instantiate(interner, args);
421 let ty = Type::new_with_resolver(db, &self.resolver, ty);
422 let mut res = ty.as_callable(db)?;
423 res.is_bound_method = true;
424 Some(res)
425 }
426
427 pub(crate) fn resolve_method_call(
428 &self,
429 db: &'db dyn HirDatabase,
430 call: &ast::MethodCallExpr,
431 ) -> Option<Function> {
432 let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
433 let (f_in_trait, substs) = self.infer()?.method_resolution(expr_id)?;
434
435 Some(self.resolve_impl_method_or_trait_def(db, f_in_trait, substs).into())
436 }
437
438 pub(crate) fn resolve_method_call_fallback(
439 &self,
440 db: &'db dyn HirDatabase,
441 call: &ast::MethodCallExpr,
442 ) -> Option<(Either<Function, Field>, Option<GenericSubstitution<'db>>)> {
443 let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
444 let inference_result = self.infer()?;
445 match inference_result.method_resolution(expr_id) {
446 Some((f_in_trait, substs)) => {
447 let (fn_, subst) =
448 self.resolve_impl_method_or_trait_def_with_subst(db, f_in_trait, substs);
449 Some((
450 Either::Left(fn_.into()),
451 Some(GenericSubstitution::new(fn_.into(), subst, self.trait_environment(db))),
452 ))
453 }
454 None => {
455 inference_result.field_resolution(expr_id).and_then(Either::left).map(|field| {
456 (Either::Right(field.into()), self.field_subst(expr_id, inference_result, db))
457 })
458 }
459 }
460 }
461
462 pub(crate) fn resolve_expr_as_callable(
463 &self,
464 db: &'db dyn HirDatabase,
465 call: &ast::Expr,
466 ) -> Option<Callable<'db>> {
467 let (orig, adjusted) = self.type_of_expr(db, &call.clone())?;
468 adjusted.unwrap_or(orig).as_callable(db)
469 }
470
471 pub(crate) fn resolve_field(
472 &self,
473 field: &ast::FieldExpr,
474 ) -> Option<Either<Field, TupleField>> {
475 let (def, ..) = self.body_()?;
476 let expr_id = self.expr_id(field.clone().into())?.as_expr()?;
477 self.infer()?.field_resolution(expr_id).map(|it| {
478 it.map_either(Into::into, |f| TupleField { owner: def, tuple: f.tuple, index: f.index })
479 })
480 }
481
482 fn field_subst(
483 &self,
484 field_expr: ExprId,
485 infer: &InferenceResult<'db>,
486 db: &'db dyn HirDatabase,
487 ) -> Option<GenericSubstitution<'db>> {
488 let body = self.store()?;
489 if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] {
490 let (adt, subst) = infer.type_of_expr_with_adjust(object_expr)?.as_adt()?;
491 return Some(GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)));
492 }
493 None
494 }
495
496 pub(crate) fn resolve_field_fallback(
497 &self,
498 db: &'db dyn HirDatabase,
499 field: &ast::FieldExpr,
500 ) -> Option<(Either<Either<Field, TupleField>, Function>, Option<GenericSubstitution<'db>>)>
501 {
502 let (def, ..) = self.body_()?;
503 let expr_id = self.expr_id(field.clone().into())?.as_expr()?;
504 let inference_result = self.infer()?;
505 match inference_result.field_resolution(expr_id) {
506 Some(field) => match field {
507 Either::Left(field) => Some((
508 Either::Left(Either::Left(field.into())),
509 self.field_subst(expr_id, inference_result, db),
510 )),
511 Either::Right(field) => Some((
512 Either::Left(Either::Right(TupleField {
513 owner: def,
514 tuple: field.tuple,
515 index: field.index,
516 })),
517 None,
518 )),
519 },
520 None => inference_result.method_resolution(expr_id).map(|(f, substs)| {
521 let (f, subst) = self.resolve_impl_method_or_trait_def_with_subst(db, f, substs);
522 (
523 Either::Right(f.into()),
524 Some(GenericSubstitution::new(f.into(), subst, self.trait_environment(db))),
525 )
526 }),
527 }
528 }
529
530 pub(crate) fn resolve_range_pat(
531 &self,
532 db: &'db dyn HirDatabase,
533 range_pat: &ast::RangePat,
534 ) -> Option<StructId> {
535 let path: ModPath = match (range_pat.op_kind()?, range_pat.start(), range_pat.end()) {
536 (RangeOp::Exclusive, None, Some(_)) => path![core::ops::RangeTo],
537 (RangeOp::Exclusive, Some(_), None) => path![core::ops::RangeFrom],
538 (RangeOp::Exclusive, Some(_), Some(_)) => path![core::ops::Range],
539 (RangeOp::Inclusive, None, Some(_)) => path![core::ops::RangeToInclusive],
540 (RangeOp::Inclusive, Some(_), Some(_)) => path![core::ops::RangeInclusive],
541
542 (RangeOp::Exclusive, None, None) => return None,
543 (RangeOp::Inclusive, None, None) => return None,
544 (RangeOp::Inclusive, Some(_), None) => return None,
545 };
546 self.resolver.resolve_known_struct(db, &path)
547 }
548
549 pub(crate) fn resolve_range_expr(
550 &self,
551 db: &'db dyn HirDatabase,
552 range_expr: &ast::RangeExpr,
553 ) -> Option<StructId> {
554 let path: ModPath = match (range_expr.op_kind()?, range_expr.start(), range_expr.end()) {
555 (RangeOp::Exclusive, None, None) => path![core::ops::RangeFull],
556 (RangeOp::Exclusive, None, Some(_)) => path![core::ops::RangeTo],
557 (RangeOp::Exclusive, Some(_), None) => path![core::ops::RangeFrom],
558 (RangeOp::Exclusive, Some(_), Some(_)) => path![core::ops::Range],
559 (RangeOp::Inclusive, None, Some(_)) => path![core::ops::RangeToInclusive],
560 (RangeOp::Inclusive, Some(_), Some(_)) => path![core::ops::RangeInclusive],
561
562 (RangeOp::Inclusive, None, None) => return None,
564 (RangeOp::Inclusive, Some(_), None) => return None,
565 };
566 self.resolver.resolve_known_struct(db, &path)
567 }
568
569 pub(crate) fn resolve_await_to_poll(
570 &self,
571 db: &'db dyn HirDatabase,
572 await_expr: &ast::AwaitExpr,
573 ) -> Option<FunctionId> {
574 let mut ty = self.ty_of_expr(await_expr.expr()?)?;
575
576 let into_future_trait = self
577 .resolver
578 .resolve_known_trait(db, &path![core::future::IntoFuture])
579 .map(Trait::from);
580
581 if let Some(into_future_trait) = into_future_trait {
582 let type_ = Type::new_with_resolver(db, &self.resolver, ty);
583 if type_.impls_trait(db, into_future_trait, &[]) {
584 let items = into_future_trait.items(db);
585 let into_future_type = items.into_iter().find_map(|item| match item {
586 AssocItem::TypeAlias(alias)
587 if alias.name(db) == Name::new_symbol_root(sym::IntoFuture) =>
588 {
589 Some(alias)
590 }
591 _ => None,
592 })?;
593 let future_trait = type_.normalize_trait_assoc_type(db, &[], into_future_type)?;
594 ty = future_trait.ty;
595 }
596 }
597
598 let poll_fn = self.lang_items(db).FuturePoll?;
599 let interner = DbInterner::new_no_crate(db);
602 let substs = GenericArgs::new_from_iter(interner, [ty.into()]);
603 Some(self.resolve_impl_method_or_trait_def(db, poll_fn, substs))
604 }
605
606 pub(crate) fn resolve_prefix_expr(
607 &self,
608 db: &'db dyn HirDatabase,
609 prefix_expr: &ast::PrefixExpr,
610 ) -> Option<FunctionId> {
611 let (_op_trait, op_fn) = match prefix_expr.op_kind()? {
612 ast::UnaryOp::Deref => {
613 let (deref_trait, deref) = self.lang_trait_fn(
617 db,
618 self.lang_items(db).Deref,
619 &Name::new_symbol_root(sym::deref),
620 )?;
621 self.infer()
622 .and_then(|infer| {
623 let expr = self.expr_id(prefix_expr.clone().into())?.as_expr()?;
624 let (func, _) = infer.method_resolution(expr)?;
625 let (deref_mut_trait, deref_mut) = self.lang_trait_fn(
626 db,
627 self.lang_items(db).DerefMut,
628 &Name::new_symbol_root(sym::deref_mut),
629 )?;
630 if func == deref_mut { Some((deref_mut_trait, deref_mut)) } else { None }
631 })
632 .unwrap_or((deref_trait, deref))
633 }
634 ast::UnaryOp::Not => {
635 self.lang_trait_fn(db, self.lang_items(db).Not, &Name::new_symbol_root(sym::not))?
636 }
637 ast::UnaryOp::Neg => {
638 self.lang_trait_fn(db, self.lang_items(db).Neg, &Name::new_symbol_root(sym::neg))?
639 }
640 };
641
642 let ty = self.ty_of_expr(prefix_expr.expr()?)?;
643
644 let interner = DbInterner::new_no_crate(db);
645 let substs = GenericArgs::new_from_iter(interner, [ty.into()]);
648
649 Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
650 }
651
652 pub(crate) fn resolve_index_expr(
653 &self,
654 db: &'db dyn HirDatabase,
655 index_expr: &ast::IndexExpr,
656 ) -> Option<FunctionId> {
657 let base_ty = self.ty_of_expr(index_expr.base()?)?;
658 let index_ty = self.ty_of_expr(index_expr.index()?)?;
659
660 let (_index_trait, index_fn) =
661 self.lang_trait_fn(db, self.lang_items(db).Index, &Name::new_symbol_root(sym::index))?;
662 let op_fn = self
663 .infer()
664 .and_then(|infer| {
665 let expr = self.expr_id(index_expr.clone().into())?.as_expr()?;
666 let (func, _) = infer.method_resolution(expr)?;
667 let (_index_mut_trait, index_mut_fn) = self.lang_trait_fn(
668 db,
669 self.lang_items(db).IndexMut,
670 &Name::new_symbol_root(sym::index_mut),
671 )?;
672 if func == index_mut_fn { Some(index_mut_fn) } else { None }
673 })
674 .unwrap_or(index_fn);
675 let interner = DbInterner::new_no_crate(db);
678 let substs = GenericArgs::new_from_iter(interner, [base_ty.into(), index_ty.into()]);
679 Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
680 }
681
682 pub(crate) fn resolve_bin_expr(
683 &self,
684 db: &'db dyn HirDatabase,
685 binop_expr: &ast::BinExpr,
686 ) -> Option<FunctionId> {
687 let op = binop_expr.op_kind()?;
688 let lhs = self.ty_of_expr(binop_expr.lhs()?)?;
689 let rhs = self.ty_of_expr(binop_expr.rhs()?)?;
690
691 let (_op_trait, op_fn) =
692 lang_items_for_bin_op(self.lang_items(db), op).and_then(|(name, lang_item)| {
693 self.lang_trait_fn(db, lang_item, &Name::new_symbol_root(name))
694 })?;
695 let interner = DbInterner::new_no_crate(db);
698 let substs = GenericArgs::new_from_iter(interner, [lhs.into(), rhs.into()]);
699
700 Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
701 }
702
703 pub(crate) fn resolve_try_expr(
704 &self,
705 db: &'db dyn HirDatabase,
706 try_expr: &ast::TryExpr,
707 ) -> Option<FunctionId> {
708 let ty = self.ty_of_expr(try_expr.expr()?)?;
709
710 let op_fn = self.lang_items(db).TryTraitBranch?;
711 let interner = DbInterner::new_no_crate(db);
714 let substs = GenericArgs::new_from_iter(interner, [ty.into()]);
715
716 Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs))
717 }
718
719 pub(crate) fn resolve_record_field(
720 &self,
721 db: &'db dyn HirDatabase,
722 field: &ast::RecordExprField,
723 ) -> Option<(Field, Option<Local>, Type<'db>, GenericSubstitution<'db>)> {
724 let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
725 let expr = ast::Expr::from(record_expr);
726 let expr_id = self.store_sm()?.node_expr(InFile::new(self.file_id, &expr))?;
727 let interner = DbInterner::new_no_crate(db);
728
729 let ast_name = field.field_name()?;
730 let local_name = ast_name.as_name();
731 let local = if field.name_ref().is_some() {
732 None
733 } else {
734 let path = Path::from_known_path_with_no_generic(ModPath::from_segments(
736 PathKind::Plain,
737 once(local_name.clone()),
738 ));
739 match self.resolver.resolve_path_in_value_ns_fully(
740 db,
741 &path,
742 name_hygiene(db, InFile::new(self.file_id, ast_name.syntax())),
743 ) {
744 Some(ValueNs::LocalBinding(binding_id)) => {
745 Some(Local { binding_id, parent: self.resolver.body_owner()? })
746 }
747 _ => None,
748 }
749 };
750 let (adt, subst) = self.infer()?.type_of_expr_or_pat(expr_id)?.as_adt()?;
751 let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?;
752 let variant_data = variant.fields(db);
753 let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
754 let field_ty = (*db.field_types(variant).get(field.local_id)?).instantiate(interner, subst);
755 Some((
756 field.into(),
757 local,
758 Type::new_with_resolver(db, &self.resolver, field_ty),
759 GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)),
760 ))
761 }
762
763 pub(crate) fn resolve_record_pat_field(
764 &self,
765 db: &'db dyn HirDatabase,
766 field: &ast::RecordPatField,
767 ) -> Option<(Field, Type<'db>, GenericSubstitution<'db>)> {
768 let interner = DbInterner::new_no_crate(db);
769 let field_name = field.field_name()?.as_name();
770 let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
771 let pat_id = self.pat_id(&record_pat.into())?;
772 let variant = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?;
773 let variant_data = variant.fields(db);
774 let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
775 let (adt, subst) = self.infer()?[pat_id.as_pat()?].as_adt()?;
776 let field_ty = (*db.field_types(variant).get(field.local_id)?).instantiate(interner, subst);
777 Some((
778 field.into(),
779 Type::new_with_resolver(db, &self.resolver, field_ty),
780 GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)),
781 ))
782 }
783
784 pub(crate) fn resolve_bind_pat_to_const(
785 &self,
786 db: &'db dyn HirDatabase,
787 pat: &ast::IdentPat,
788 ) -> Option<ModuleDef> {
789 let expr_or_pat_id = self.pat_id(&pat.clone().into())?;
790 let store = self.store()?;
791
792 let path = match expr_or_pat_id {
793 ExprOrPatId::ExprId(idx) => match &store[idx] {
794 Expr::Path(path) => path,
795 _ => return None,
796 },
797 ExprOrPatId::PatId(idx) => match &store[idx] {
798 Pat::Path(path) => path,
799 _ => return None,
800 },
801 };
802
803 let body_owner = self.resolver.body_owner();
804 let res = resolve_hir_value_path(db, &self.resolver, body_owner, path, HygieneId::ROOT)?;
805 match res {
806 PathResolution::Def(def) => Some(def),
807 _ => None,
808 }
809 }
810
811 pub(crate) fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option<crate::TypeParam> {
812 let name = name.as_name();
813 self.resolver
814 .all_generic_params()
815 .find_map(|(params, parent)| params.find_type_by_name(&name, *parent))
816 .map(crate::TypeParam::from)
817 }
818
819 pub(crate) fn resolve_offset_of_field(
820 &self,
821 db: &'db dyn HirDatabase,
822 name_ref: &ast::NameRef,
823 ) -> Option<(Either<crate::Variant, crate::Field>, GenericSubstitution<'db>)> {
824 let offset_of_expr = ast::OffsetOfExpr::cast(name_ref.syntax().parent()?)?;
825 let container = offset_of_expr.ty()?;
826 let container = self.type_of_type(db, &container)?;
827
828 let trait_env = container.env;
829
830 let interner = DbInterner::new_with(db, trait_env.krate);
831 let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
832
833 let mut container = Either::Right(container.ty);
834 for field_name in offset_of_expr.fields() {
835 if let Either::Right(container) = &mut container {
836 *container = structurally_normalize_ty(&infcx, *container, trait_env.param_env);
837 }
838 let handle_variants =
839 |variant: VariantId, subst: GenericArgs<'db>, container: &mut _| {
840 let fields = variant.fields(db);
841 let field = fields.field(&field_name.as_name())?;
842 let field_types = db.field_types(variant);
843 *container = Either::Right(field_types[field].instantiate(interner, subst));
844 let generic_def = match variant {
845 VariantId::EnumVariantId(it) => it.loc(db).parent.into(),
846 VariantId::StructId(it) => it.into(),
847 VariantId::UnionId(it) => it.into(),
848 };
849 Some((
850 Either::Right(Field { parent: variant.into(), id: field }),
851 generic_def,
852 subst,
853 ))
854 };
855 let temp_ty = Ty::new_error(interner, ErrorGuaranteed);
856 let (field_def, generic_def, subst) =
857 match std::mem::replace(&mut container, Either::Right(temp_ty)) {
858 Either::Left((variant_id, subst)) => {
859 handle_variants(VariantId::from(variant_id), subst, &mut container)?
860 }
861 Either::Right(container_ty) => match container_ty.kind() {
862 TyKind::Adt(adt_def, subst) => match adt_def.def_id().0 {
863 AdtId::StructId(id) => {
864 handle_variants(id.into(), subst, &mut container)?
865 }
866 AdtId::UnionId(id) => {
867 handle_variants(id.into(), subst, &mut container)?
868 }
869 AdtId::EnumId(id) => {
870 let variants = id.enum_variants(db);
871 let variant = variants.variant(&field_name.as_name())?;
872 container = Either::Left((variant, subst));
873 (Either::Left(Variant { id: variant }), id.into(), subst)
874 }
875 },
876 _ => return None,
877 },
878 };
879
880 if field_name.syntax().text_range() == name_ref.syntax().text_range() {
881 return Some((field_def, GenericSubstitution::new(generic_def, subst, trait_env)));
882 }
883 }
884 never!("the `NameRef` is a child of the `OffsetOfExpr`, we should've visited it");
885 None
886 }
887
888 pub(crate) fn resolve_path(
889 &self,
890 db: &'db dyn HirDatabase,
891 path: &ast::Path,
892 ) -> Option<(PathResolution, Option<GenericSubstitution<'db>>)> {
893 let parent = path.syntax().parent();
894 let parent = || parent.clone();
895
896 let mut prefer_value_ns = false;
897 let resolved = (|| {
898 let infer = self.infer()?;
899 if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) {
900 let expr_id = self.expr_id(path_expr.into())?;
901 if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_id) {
902 let (assoc, subst) = match assoc {
903 CandidateId::FunctionId(f_in_trait) => {
904 match infer.type_of_expr_or_pat(expr_id) {
905 None => {
906 let subst = GenericSubstitution::new(
907 f_in_trait.into(),
908 subs,
909 self.trait_environment(db),
910 );
911 (AssocItemId::from(f_in_trait), subst)
912 }
913 Some(func_ty) => {
914 if let TyKind::FnDef(_fn_def, subs) = func_ty.kind() {
915 let (fn_, subst) = self
916 .resolve_impl_method_or_trait_def_with_subst(
917 db, f_in_trait, subs,
918 );
919 let subst = GenericSubstitution::new(
920 fn_.into(),
921 subst,
922 self.trait_environment(db),
923 );
924 (fn_.into(), subst)
925 } else {
926 let subst = GenericSubstitution::new(
927 f_in_trait.into(),
928 subs,
929 self.trait_environment(db),
930 );
931 (f_in_trait.into(), subst)
932 }
933 }
934 }
935 }
936 CandidateId::ConstId(const_id) => {
937 let (konst, subst) =
938 self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);
939 let subst = GenericSubstitution::new(
940 konst.into(),
941 subst,
942 self.trait_environment(db),
943 );
944 (konst.into(), subst)
945 }
946 };
947
948 return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst)));
949 }
950 if let Some(VariantId::EnumVariantId(variant)) =
951 infer.variant_resolution_for_expr_or_pat(expr_id)
952 {
953 return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None));
954 }
955 prefer_value_ns = true;
956 } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
957 let expr_or_pat_id = self.pat_id(&path_pat.into())?;
958 if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_or_pat_id)
959 {
960 let (assoc, subst) = match assoc {
961 CandidateId::ConstId(const_id) => {
962 let (konst, subst) =
963 self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);
964 let subst = GenericSubstitution::new(
965 konst.into(),
966 subst,
967 self.trait_environment(db),
968 );
969 (AssocItemId::from(konst), subst)
970 }
971 CandidateId::FunctionId(function_id) => (
972 function_id.into(),
973 GenericSubstitution::new(
974 function_id.into(),
975 subs,
976 self.trait_environment(db),
977 ),
978 ),
979 };
980 return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst)));
981 }
982 if let Some(VariantId::EnumVariantId(variant)) =
983 infer.variant_resolution_for_expr_or_pat(expr_or_pat_id)
984 {
985 return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None));
986 }
987 } else if let Some(rec_lit) = parent().and_then(ast::RecordExpr::cast) {
988 let expr_id = self.expr_id(rec_lit.into())?;
989 if let Some(VariantId::EnumVariantId(variant)) =
990 infer.variant_resolution_for_expr_or_pat(expr_id)
991 {
992 return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None));
993 }
994 } else {
995 let record_pat = parent().and_then(ast::RecordPat::cast).map(ast::Pat::from);
996 let tuple_struct_pat =
997 || parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from);
998 if let Some(pat) = record_pat.or_else(tuple_struct_pat) {
999 let pat_id = self.pat_id(&pat)?;
1000 let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id.as_pat()?);
1001 if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat {
1002 return Some((
1003 PathResolution::Def(ModuleDef::Variant(variant.into())),
1004 None,
1005 ));
1006 }
1007 }
1008 }
1009 None
1010 })();
1011 if resolved.is_some() {
1012 return resolved;
1013 }
1014
1015 let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
1017 let hir_path =
1018 collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;
1019 let parent_hir_path = path
1020 .parent_path()
1021 .and_then(|p| collector.lower_path(p, &mut ExprCollector::impl_trait_error_allocator));
1022 let (store, _) = collector.store.finish();
1023
1024 if let Some(use_tree) = parent().and_then(ast::UseTree::cast)
1027 && use_tree.coloncolon_token().is_some()
1028 {
1029 return resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store)
1030 .map(|it| (it, None));
1031 }
1032
1033 let meta_path = path
1034 .syntax()
1035 .ancestors()
1036 .take_while(|it| {
1037 let kind = it.kind();
1038 ast::Path::can_cast(kind) || ast::Meta::can_cast(kind)
1039 })
1040 .last()
1041 .and_then(ast::Meta::cast);
1042
1043 if let Some(parent_hir_path) = parent_hir_path {
1046 return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store) {
1047 None if meta_path.is_some() => path
1048 .first_segment()
1049 .and_then(|it| it.name_ref())
1050 .and_then(|name_ref| {
1051 ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
1052 .map(PathResolution::ToolModule)
1053 })
1054 .map(|it| (it, None)),
1055 Some(it) if matches!(it, PathResolution::Def(ModuleDef::BuiltinType(_))) => {
1066 if let Some(mod_path) = hir_path.mod_path()
1067 && let Some(ModuleDefId::ModuleId(id)) =
1068 self.resolver.resolve_module_path_in_items(db, mod_path).take_types()
1069 {
1070 let parent_hir_name = parent_hir_path.segments().get(1).map(|it| it.name);
1071 let module = crate::Module { id };
1072 if module
1073 .scope(db, None)
1074 .into_iter()
1075 .any(|(name, _)| Some(&name) == parent_hir_name)
1076 {
1077 return Some((PathResolution::Def(ModuleDef::Module(module)), None));
1078 };
1079 }
1080 Some((it, None))
1081 }
1082 res => res.map(|it| (it, None)),
1086 };
1087 } else if let Some(meta_path) = meta_path {
1088 if let Some(name_ref) = path.as_single_name_ref() {
1092 let builtin = BuiltinAttr::builtin(&name_ref.text());
1093 if builtin.is_some() {
1094 return builtin.map(|it| (PathResolution::BuiltinAttr(it), None));
1095 }
1096
1097 if let Some(attr) = meta_path.parent_attr() {
1098 let adt = if let Some(field) =
1099 attr.syntax().parent().and_then(ast::RecordField::cast)
1100 {
1101 field.syntax().ancestors().take(4).find_map(ast::Adt::cast)
1102 } else if let Some(field) =
1103 attr.syntax().parent().and_then(ast::TupleField::cast)
1104 {
1105 field.syntax().ancestors().take(4).find_map(ast::Adt::cast)
1106 } else if let Some(variant) =
1107 attr.syntax().parent().and_then(ast::Variant::cast)
1108 {
1109 variant.syntax().ancestors().nth(2).and_then(ast::Adt::cast)
1110 } else {
1111 None
1112 };
1113 if let Some(adt) = adt {
1114 let ast_id = db.ast_id_map(self.file_id).ast_id(&adt);
1115 if let Some(helpers) = self
1116 .resolver
1117 .def_map()
1118 .derive_helpers_in_scope(InFile::new(self.file_id, ast_id))
1119 {
1120 let name_ref = name_ref.as_name();
1122 for (macro_id, mut helpers) in
1123 helpers.iter().chunk_by(|(_, macro_id, ..)| macro_id).into_iter()
1124 {
1125 if let Some(idx) = helpers.position(|(name, ..)| *name == name_ref)
1126 {
1127 return Some((
1128 PathResolution::DeriveHelper(DeriveHelper {
1129 derive: *macro_id,
1130 idx: idx as u32,
1131 }),
1132 None,
1133 ));
1134 }
1135 }
1136 }
1137 }
1138 }
1139 }
1140 return match resolve_hir_path_as_attr_macro(db, &self.resolver, &hir_path) {
1141 Some(m) => Some((PathResolution::Def(ModuleDef::Macro(m)), None)),
1142 None => path
1145 .first_segment()
1146 .and_then(|it| it.name_ref())
1147 .and_then(|name_ref| {
1148 ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
1149 .map(PathResolution::ToolModule)
1150 })
1151 .map(|it| (it, None)),
1152 };
1153 }
1154 if parent().is_some_and(|it| ast::Visibility::can_cast(it.kind())) {
1155 resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &store).map(|it| (it, None))
1157 } else {
1158 let res = resolve_hir_path_(
1160 db,
1161 &self.resolver,
1162 &hir_path,
1163 prefer_value_ns,
1164 name_hygiene(db, InFile::new(self.file_id, path.syntax())),
1165 Some(&store),
1166 false,
1167 )
1168 .any()?;
1169 let subst = (|| {
1170 let parent = parent()?;
1171 let ty = if let Some(expr) = ast::Expr::cast(parent.clone()) {
1172 let expr_id = self.expr_id(expr)?;
1173 self.infer()?.type_of_expr_or_pat(expr_id)?
1174 } else if let Some(pat) = ast::Pat::cast(parent) {
1175 let pat_id = self.pat_id(&pat)?;
1176 self.infer()?[pat_id]
1177 } else {
1178 return None;
1179 };
1180 let env = self.trait_environment(db);
1181 let (subst, expected_resolution) = match ty.kind() {
1182 TyKind::Adt(adt_def, subst) => {
1183 let adt_id = adt_def.def_id().0;
1184 (
1185 GenericSubstitution::new(adt_id.into(), subst, env),
1186 PathResolution::Def(ModuleDef::Adt(adt_id.into())),
1187 )
1188 }
1189 TyKind::Alias(AliasTyKind::Projection, alias) => {
1190 let assoc_id = alias.def_id.expect_type_alias();
1191 (
1192 GenericSubstitution::new(assoc_id.into(), alias.args, env),
1193 PathResolution::Def(ModuleDef::TypeAlias(assoc_id.into())),
1194 )
1195 }
1196 TyKind::FnDef(fn_id, subst) => {
1197 let generic_def_id = match fn_id.0 {
1198 CallableDefId::StructId(id) => id.into(),
1199 CallableDefId::FunctionId(id) => id.into(),
1200 CallableDefId::EnumVariantId(_) => return None,
1201 };
1202 (
1203 GenericSubstitution::new(generic_def_id, subst, env),
1204 PathResolution::Def(ModuleDefId::from(fn_id.0).into()),
1205 )
1206 }
1207 _ => return None,
1208 };
1209 if res != expected_resolution {
1210 return None;
1212 }
1213 Some(subst)
1214 })();
1215 Some((res, subst))
1216 }
1217 }
1218
1219 pub(crate) fn resolve_hir_path_per_ns(
1220 &self,
1221 db: &dyn HirDatabase,
1222 path: &ast::Path,
1223 ) -> Option<PathResolutionPerNs> {
1224 let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
1225 let hir_path =
1226 collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;
1227 let (store, _) = collector.store.finish();
1228 Some(resolve_hir_path_(
1229 db,
1230 &self.resolver,
1231 &hir_path,
1232 false,
1233 name_hygiene(db, InFile::new(self.file_id, path.syntax())),
1234 Some(&store),
1235 true,
1236 ))
1237 }
1238
1239 pub(crate) fn record_literal_missing_fields(
1240 &self,
1241 db: &'db dyn HirDatabase,
1242 literal: &ast::RecordExpr,
1243 ) -> Option<Vec<(Field, Type<'db>)>> {
1244 let body = self.store()?;
1245 let infer = self.infer()?;
1246
1247 let expr_id = self.expr_id(literal.clone().into())?;
1248 let substs = infer[expr_id].as_adt()?.1;
1249
1250 let (variant, missing_fields, _exhaustive) = match expr_id {
1251 ExprOrPatId::ExprId(expr_id) => {
1252 record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?
1253 }
1254 ExprOrPatId::PatId(pat_id) => {
1255 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?
1256 }
1257 };
1258 let res = self.missing_fields(db, substs, variant, missing_fields);
1259 Some(res)
1260 }
1261
1262 pub(crate) fn record_pattern_missing_fields(
1263 &self,
1264 db: &'db dyn HirDatabase,
1265 pattern: &ast::RecordPat,
1266 ) -> Option<Vec<(Field, Type<'db>)>> {
1267 let body = self.store()?;
1268 let infer = self.infer()?;
1269
1270 let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;
1271 let substs = infer[pat_id].as_adt()?.1;
1272
1273 let (variant, missing_fields, _exhaustive) =
1274 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
1275 let res = self.missing_fields(db, substs, variant, missing_fields);
1276 Some(res)
1277 }
1278
1279 fn missing_fields(
1280 &self,
1281 db: &'db dyn HirDatabase,
1282 substs: GenericArgs<'db>,
1283 variant: VariantId,
1284 missing_fields: Vec<LocalFieldId>,
1285 ) -> Vec<(Field, Type<'db>)> {
1286 let interner = DbInterner::new_no_crate(db);
1287 let field_types = db.field_types(variant);
1288
1289 missing_fields
1290 .into_iter()
1291 .map(|local_id| {
1292 let field = FieldId { parent: variant, local_id };
1293 let ty = field_types[local_id].instantiate(interner, substs);
1294 (field.into(), Type::new_with_resolver_inner(db, &self.resolver, ty))
1295 })
1296 .collect()
1297 }
1298
1299 pub(crate) fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
1300 let infer = self.infer()?;
1301 let expr_id = self.expr_id(record_lit.into())?;
1302 infer.variant_resolution_for_expr_or_pat(expr_id)
1303 }
1304
1305 pub(crate) fn is_unsafe_macro_call_expr(
1306 &self,
1307 db: &'db dyn HirDatabase,
1308 macro_expr: InFile<&ast::MacroExpr>,
1309 ) -> bool {
1310 if let Some((def, body, sm, Some(infer))) = self.body_()
1311 && let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr)
1312 {
1313 let mut is_unsafe = false;
1314 let mut walk_expr = |expr_id| {
1315 unsafe_operations(db, infer, def, body, expr_id, &mut |_, inside_unsafe_block| {
1316 is_unsafe |= inside_unsafe_block == InsideUnsafeBlock::No
1317 })
1318 };
1319 match expanded_expr {
1320 ExprOrPatId::ExprId(expanded_expr) => walk_expr(expanded_expr),
1321 ExprOrPatId::PatId(expanded_pat) => {
1322 body.walk_exprs_in_pat(expanded_pat, &mut walk_expr)
1323 }
1324 }
1325 return is_unsafe;
1326 }
1327 false
1328 }
1329
1330 pub(crate) fn resolve_offset_in_format_args(
1332 &self,
1333 db: &'db dyn HirDatabase,
1334 format_args: InFile<&ast::FormatArgsExpr>,
1335 offset: TextSize,
1336 ) -> Option<(TextRange, Option<PathResolution>)> {
1337 let (hygiene, implicits) = self.store_sm()?.implicit_format_args(format_args)?;
1338 implicits.iter().find(|(range, _)| range.contains_inclusive(offset)).map(|(range, name)| {
1339 (
1340 *range,
1341 resolve_hir_value_path(
1342 db,
1343 &self.resolver,
1344 self.resolver.body_owner(),
1345 &Path::from_known_path_with_no_generic(ModPath::from_segments(
1346 PathKind::Plain,
1347 Some(name.clone()),
1348 )),
1349 hygiene,
1350 ),
1351 )
1352 })
1353 }
1354
1355 pub(crate) fn resolve_offset_in_asm_template(
1356 &self,
1357 asm: InFile<&ast::AsmExpr>,
1358 line: usize,
1359 offset: TextSize,
1360 ) -> Option<(DefWithBodyId, (ExprId, TextRange, usize))> {
1361 let (def, _, body_source_map, _) = self.body_()?;
1362 let (expr, args) = body_source_map.asm_template_args(asm)?;
1363 Some(def).zip(
1364 args.get(line)?
1365 .iter()
1366 .find(|(range, _)| range.contains_inclusive(offset))
1367 .map(|(range, idx)| (expr, *range, *idx)),
1368 )
1369 }
1370
1371 pub(crate) fn as_format_args_parts<'a>(
1372 &'a self,
1373 db: &'a dyn HirDatabase,
1374 format_args: InFile<&ast::FormatArgsExpr>,
1375 ) -> Option<impl Iterator<Item = (TextRange, Option<PathResolution>)> + 'a> {
1376 let (hygiene, names) = self.store_sm()?.implicit_format_args(format_args)?;
1377 Some(names.iter().map(move |(range, name)| {
1378 (
1379 *range,
1380 resolve_hir_value_path(
1381 db,
1382 &self.resolver,
1383 self.resolver.body_owner(),
1384 &Path::from_known_path_with_no_generic(ModPath::from_segments(
1385 PathKind::Plain,
1386 Some(name.clone()),
1387 )),
1388 hygiene,
1389 ),
1390 )
1391 }))
1392 }
1393
1394 pub(crate) fn as_asm_parts(
1395 &self,
1396 asm: InFile<&ast::AsmExpr>,
1397 ) -> Option<(DefWithBodyId, (ExprId, &[Vec<(TextRange, usize)>]))> {
1398 let (def, _, body_source_map, _) = self.body_()?;
1399 Some(def).zip(body_source_map.asm_template_args(asm))
1400 }
1401
1402 fn resolve_impl_method_or_trait_def(
1403 &self,
1404 db: &'db dyn HirDatabase,
1405 func: FunctionId,
1406 substs: GenericArgs<'db>,
1407 ) -> FunctionId {
1408 self.resolve_impl_method_or_trait_def_with_subst(db, func, substs).0
1409 }
1410
1411 fn resolve_impl_method_or_trait_def_with_subst(
1412 &self,
1413 db: &'db dyn HirDatabase,
1414 func: FunctionId,
1415 substs: GenericArgs<'db>,
1416 ) -> (FunctionId, GenericArgs<'db>) {
1417 let owner = match self.resolver.body_owner() {
1418 Some(it) => it,
1419 None => return (func, substs),
1420 };
1421 let env = self.param_and(db.trait_environment_for_body(owner));
1422 db.lookup_impl_method(env, func, substs)
1423 }
1424
1425 fn resolve_impl_const_or_trait_def_with_subst(
1426 &self,
1427 db: &'db dyn HirDatabase,
1428 const_id: ConstId,
1429 subs: GenericArgs<'db>,
1430 ) -> (ConstId, GenericArgs<'db>) {
1431 let owner = match self.resolver.body_owner() {
1432 Some(it) => it,
1433 None => return (const_id, subs),
1434 };
1435 let env = self.param_and(db.trait_environment_for_body(owner));
1436 let interner = DbInterner::new_with(db, env.krate);
1437 let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
1438 method_resolution::lookup_impl_const(&infcx, env.param_env, const_id, subs)
1439 }
1440
1441 fn lang_items<'a>(&self, db: &'a dyn HirDatabase) -> &'a LangItems {
1442 hir_def::lang_item::lang_items(db, self.resolver.krate())
1443 }
1444
1445 fn lang_trait_fn(
1446 &self,
1447 db: &'db dyn HirDatabase,
1448 lang_trait: Option<TraitId>,
1449 method_name: &Name,
1450 ) -> Option<(TraitId, FunctionId)> {
1451 let trait_id = lang_trait?;
1452 let fn_id = trait_id.trait_items(db).method_by_name(method_name)?;
1453 Some((trait_id, fn_id))
1454 }
1455
1456 fn ty_of_expr(&self, expr: ast::Expr) -> Option<Ty<'db>> {
1457 self.infer()?.type_of_expr_or_pat(self.expr_id(expr)?)
1458 }
1459}
1460
1461fn scope_for(
1462 db: &dyn HirDatabase,
1463 scopes: &ExprScopes,
1464 source_map: &BodySourceMap,
1465 node: InFile<&SyntaxNode>,
1466) -> Option<ScopeId> {
1467 node.ancestors_with_macros(db)
1468 .take_while(|it| {
1469 let kind = it.kind();
1470 !ast::Item::can_cast(kind)
1471 || ast::MacroCall::can_cast(kind)
1472 || ast::Use::can_cast(kind)
1473 || ast::AsmExpr::can_cast(kind)
1474 })
1475 .filter_map(|it| it.map(ast::Expr::cast).transpose())
1476 .filter_map(|it| source_map.node_expr(it.as_ref())?.as_expr())
1477 .find_map(|it| scopes.scope_for(it))
1478}
1479
1480fn scope_for_offset(
1481 db: &dyn HirDatabase,
1482 scopes: &ExprScopes,
1483 source_map: &BodySourceMap,
1484 from_file: HirFileId,
1485 offset: TextSize,
1486) -> Option<ScopeId> {
1487 scopes
1488 .scope_by_expr()
1489 .iter()
1490 .filter_map(|(id, scope)| {
1491 let InFile { file_id, value } = source_map.expr_syntax(id).ok()?;
1492 if from_file == file_id {
1493 return Some((value.text_range(), scope));
1494 }
1495
1496 let source = iter::successors(file_id.macro_file().map(|it| it.call_node(db)), |it| {
1498 Some(it.file_id.macro_file()?.call_node(db))
1499 })
1500 .find(|it| it.file_id == from_file)
1501 .filter(|it| it.kind() == SyntaxKind::MACRO_CALL)?;
1502 Some((source.text_range(), scope))
1503 })
1504 .filter(|(expr_range, _scope)| expr_range.start() <= offset && offset <= expr_range.end())
1505 .min_by_key(|(expr_range, _scope)| expr_range.len())
1507 .map(|(expr_range, scope)| {
1508 adjust(db, scopes, source_map, expr_range, from_file, offset).unwrap_or(*scope)
1509 })
1510}
1511
1512fn adjust(
1515 db: &dyn HirDatabase,
1516 scopes: &ExprScopes,
1517 source_map: &BodySourceMap,
1518 expr_range: TextRange,
1519 from_file: HirFileId,
1520 offset: TextSize,
1521) -> Option<ScopeId> {
1522 let child_scopes = scopes
1523 .scope_by_expr()
1524 .iter()
1525 .filter_map(|(id, scope)| {
1526 let source = source_map.expr_syntax(id).ok()?;
1527 if source.file_id != from_file {
1529 return None;
1530 }
1531 let root = source.file_syntax(db);
1532 let node = source.value.to_node(&root);
1533 Some((node.syntax().text_range(), scope))
1534 })
1535 .filter(|&(range, _)| {
1536 range.start() <= offset && expr_range.contains_range(range) && range != expr_range
1537 });
1538
1539 child_scopes
1540 .max_by(|&(r1, _), &(r2, _)| {
1541 if r1.contains_range(r2) {
1542 std::cmp::Ordering::Greater
1543 } else if r2.contains_range(r1) {
1544 std::cmp::Ordering::Less
1545 } else {
1546 r1.start().cmp(&r2.start())
1547 }
1548 })
1549 .map(|(_ptr, scope)| *scope)
1550}
1551
1552#[inline]
1553pub(crate) fn resolve_hir_path(
1554 db: &dyn HirDatabase,
1555 resolver: &Resolver<'_>,
1556 path: &Path,
1557 hygiene: HygieneId,
1558 store: Option<&ExpressionStore>,
1559) -> Option<PathResolution> {
1560 resolve_hir_path_(db, resolver, path, false, hygiene, store, false).any()
1561}
1562
1563#[inline]
1564pub(crate) fn resolve_hir_path_as_attr_macro(
1565 db: &dyn HirDatabase,
1566 resolver: &Resolver<'_>,
1567 path: &Path,
1568) -> Option<Macro> {
1569 resolver
1570 .resolve_path_as_macro(db, path.mod_path()?, Some(MacroSubNs::Attr))
1571 .map(|(it, _)| it)
1572 .map(Into::into)
1573}
1574
1575fn resolve_hir_path_(
1576 db: &dyn HirDatabase,
1577 resolver: &Resolver<'_>,
1578 path: &Path,
1579 prefer_value_ns: bool,
1580 hygiene: HygieneId,
1581 store: Option<&ExpressionStore>,
1582 resolve_per_ns: bool,
1583) -> PathResolutionPerNs {
1584 let types = || {
1585 let (ty, unresolved) = match path.type_anchor() {
1586 Some(type_ref) => resolver.generic_def().and_then(|def| {
1587 let (_, res) =
1588 TyLoweringContext::new(db, resolver, store?, def, LifetimeElisionKind::Infer)
1589 .lower_ty_ext(type_ref);
1590 res.map(|ty_ns| (ty_ns, path.segments().first()))
1591 }),
1592 None => {
1593 let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db, path)?;
1594 match remaining_idx {
1595 Some(remaining_idx) => {
1596 if remaining_idx + 1 == path.segments().len() {
1597 Some((ty, path.segments().last()))
1598 } else {
1599 None
1600 }
1601 }
1602 None => Some((ty, None)),
1603 }
1604 }
1605 }?;
1606
1607 if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty)
1610 && let Some(type_alias_id) =
1611 trait_id.trait_items(db).associated_type_by_name(unresolved.name)
1612 {
1613 return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
1614 }
1615
1616 let res = match ty {
1617 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
1618 TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()),
1619 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
1620 PathResolution::Def(Adt::from(it).into())
1621 }
1622 TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
1623 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
1624 TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
1625 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
1626 TypeNs::ModuleId(it) => PathResolution::Def(ModuleDef::Module(it.into())),
1627 };
1628 match unresolved {
1629 Some(unresolved) => resolver
1630 .generic_def()
1631 .and_then(|def| {
1632 hir_ty::associated_type_shorthand_candidates(
1633 db,
1634 def,
1635 res.in_type_ns()?,
1636 |name, _| name == unresolved.name,
1637 )
1638 })
1639 .map(TypeAlias::from)
1640 .map(Into::into)
1641 .map(PathResolution::Def),
1642 None => Some(res),
1643 }
1644 };
1645
1646 let body_owner = resolver.body_owner();
1647 let values = || resolve_hir_value_path(db, resolver, body_owner, path, hygiene);
1648
1649 let items = || {
1650 resolver
1651 .resolve_module_path_in_items(db, path.mod_path()?)
1652 .take_types()
1653 .map(|it| PathResolution::Def(it.into()))
1654 };
1655
1656 let macros = || {
1657 resolver
1658 .resolve_path_as_macro(db, path.mod_path()?, None)
1659 .map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into())))
1660 };
1661
1662 if resolve_per_ns {
1663 PathResolutionPerNs {
1664 type_ns: types().or_else(items),
1665 value_ns: values(),
1666 macro_ns: macros(),
1667 }
1668 } else {
1669 let res = if prefer_value_ns {
1670 values()
1671 .map(|value_ns| PathResolutionPerNs::new(None, Some(value_ns), None))
1672 .unwrap_or_else(|| PathResolutionPerNs::new(types(), None, None))
1673 } else {
1674 types()
1675 .map(|type_ns| PathResolutionPerNs::new(Some(type_ns), None, None))
1676 .unwrap_or_else(|| PathResolutionPerNs::new(None, values(), None))
1677 };
1678
1679 if res.any().is_some() {
1680 res
1681 } else if let Some(type_ns) = items() {
1682 PathResolutionPerNs::new(Some(type_ns), None, None)
1683 } else {
1684 PathResolutionPerNs::new(None, None, macros())
1685 }
1686 }
1687}
1688
1689fn resolve_hir_value_path(
1690 db: &dyn HirDatabase,
1691 resolver: &Resolver<'_>,
1692 body_owner: Option<DefWithBodyId>,
1693 path: &Path,
1694 hygiene: HygieneId,
1695) -> Option<PathResolution> {
1696 resolver.resolve_path_in_value_ns_fully(db, path, hygiene).and_then(|val| {
1697 let res = match val {
1698 ValueNs::LocalBinding(binding_id) => {
1699 let var = Local { parent: body_owner?, binding_id };
1700 PathResolution::Local(var)
1701 }
1702 ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()),
1703 ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()),
1704 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
1705 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
1706 ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
1707 ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
1708 ValueNs::GenericParam(id) => PathResolution::ConstParam(id.into()),
1709 };
1710 Some(res)
1711 })
1712}
1713
1714fn resolve_hir_path_qualifier(
1728 db: &dyn HirDatabase,
1729 resolver: &Resolver<'_>,
1730 path: &Path,
1731 store: &ExpressionStore,
1732) -> Option<PathResolution> {
1733 (|| {
1734 let (ty, unresolved) = match path.type_anchor() {
1735 Some(type_ref) => resolver.generic_def().and_then(|def| {
1736 let (_, res) =
1737 TyLoweringContext::new(db, resolver, store, def, LifetimeElisionKind::Infer)
1738 .lower_ty_ext(type_ref);
1739 res.map(|ty_ns| (ty_ns, path.segments().first()))
1740 }),
1741 None => {
1742 let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db, path)?;
1743 match remaining_idx {
1744 Some(remaining_idx) => {
1745 if remaining_idx + 1 == path.segments().len() {
1746 Some((ty, path.segments().last()))
1747 } else {
1748 None
1749 }
1750 }
1751 None => Some((ty, None)),
1752 }
1753 }
1754 }?;
1755
1756 if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty)
1759 && let Some(type_alias_id) =
1760 trait_id.trait_items(db).associated_type_by_name(unresolved.name)
1761 {
1762 return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
1763 }
1764
1765 let res = match ty {
1766 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
1767 TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()),
1768 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
1769 PathResolution::Def(Adt::from(it).into())
1770 }
1771 TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
1772 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
1773 TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
1774 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
1775 TypeNs::ModuleId(it) => PathResolution::Def(ModuleDef::Module(it.into())),
1776 };
1777 match unresolved {
1778 Some(unresolved) => resolver
1779 .generic_def()
1780 .and_then(|def| {
1781 hir_ty::associated_type_shorthand_candidates(
1782 db,
1783 def,
1784 res.in_type_ns()?,
1785 |name, _| name == unresolved.name,
1786 )
1787 })
1788 .map(TypeAlias::from)
1789 .map(Into::into)
1790 .map(PathResolution::Def),
1791 None => Some(res),
1792 }
1793 })()
1794 .or_else(|| {
1795 resolver
1796 .resolve_module_path_in_items(db, path.mod_path()?)
1797 .take_types()
1798 .map(|it| PathResolution::Def(it.into()))
1799 })
1800}
1801
1802pub(crate) fn name_hygiene(db: &dyn HirDatabase, name: InFile<&SyntaxNode>) -> HygieneId {
1803 let Some(macro_file) = name.file_id.macro_file() else {
1804 return HygieneId::ROOT;
1805 };
1806 let span_map = db.expansion_span_map(macro_file);
1807 let ctx = span_map.span_at(name.value.text_range().start()).ctx;
1808 HygieneId::new(ctx.opaque_and_semitransparent(db))
1809}