aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r--crates/ra_hir/src/ty/infer.rs73
1 files changed, 54 insertions, 19 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 5e4d49ffb..268d2c110 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -29,6 +29,7 @@ use crate::{
29 Function, StructField, Path, Name, 29 Function, StructField, Path, Name,
30 FnSignature, AdtDef, 30 FnSignature, AdtDef,
31 HirDatabase, 31 HirDatabase,
32 ImplItem,
32 type_ref::{TypeRef, Mutability}, 33 type_ref::{TypeRef, Mutability},
33 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, 34 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self},
34 generics::GenericParams, 35 generics::GenericParams,
@@ -54,6 +55,14 @@ pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> {
54 Arc::new(ctx.resolve_all()) 55 Arc::new(ctx.resolve_all())
55} 56}
56 57
58#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
59enum ExprOrPatId {
60 ExprId(ExprId),
61 PatId(PatId),
62}
63
64impl_froms!(ExprOrPatId: ExprId, PatId);
65
57/// The result of type inference: A mapping from expressions and patterns to types. 66/// The result of type inference: A mapping from expressions and patterns to types.
58#[derive(Clone, PartialEq, Eq, Debug)] 67#[derive(Clone, PartialEq, Eq, Debug)]
59pub struct InferenceResult { 68pub struct InferenceResult {
@@ -61,6 +70,8 @@ pub struct InferenceResult {
61 method_resolutions: FxHashMap<ExprId, Function>, 70 method_resolutions: FxHashMap<ExprId, Function>,
62 /// For each field access expr, records the field it resolves to. 71 /// For each field access expr, records the field it resolves to.
63 field_resolutions: FxHashMap<ExprId, StructField>, 72 field_resolutions: FxHashMap<ExprId, StructField>,
73 /// For each associated item record what it resolves to
74 assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>,
64 pub(super) type_of_expr: ArenaMap<ExprId, Ty>, 75 pub(super) type_of_expr: ArenaMap<ExprId, Ty>,
65 pub(super) type_of_pat: ArenaMap<PatId, Ty>, 76 pub(super) type_of_pat: ArenaMap<PatId, Ty>,
66} 77}
@@ -72,6 +83,12 @@ impl InferenceResult {
72 pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> { 83 pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> {
73 self.field_resolutions.get(&expr).map(|it| *it) 84 self.field_resolutions.get(&expr).map(|it| *it)
74 } 85 }
86 pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<ImplItem> {
87 self.assoc_resolutions.get(&id.into()).map(|it| *it)
88 }
89 pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> {
90 self.assoc_resolutions.get(&id.into()).map(|it| *it)
91 }
75} 92}
76 93
77impl Index<ExprId> for InferenceResult { 94impl Index<ExprId> for InferenceResult {
@@ -99,6 +116,7 @@ struct InferenceContext<'a, D: HirDatabase> {
99 var_unification_table: InPlaceUnificationTable<TypeVarId>, 116 var_unification_table: InPlaceUnificationTable<TypeVarId>,
100 method_resolutions: FxHashMap<ExprId, Function>, 117 method_resolutions: FxHashMap<ExprId, Function>,
101 field_resolutions: FxHashMap<ExprId, StructField>, 118 field_resolutions: FxHashMap<ExprId, StructField>,
119 assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>,
102 type_of_expr: ArenaMap<ExprId, Ty>, 120 type_of_expr: ArenaMap<ExprId, Ty>,
103 type_of_pat: ArenaMap<PatId, Ty>, 121 type_of_pat: ArenaMap<PatId, Ty>,
104 /// The return type of the function being inferred. 122 /// The return type of the function being inferred.
@@ -110,6 +128,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
110 InferenceContext { 128 InferenceContext {
111 method_resolutions: FxHashMap::default(), 129 method_resolutions: FxHashMap::default(),
112 field_resolutions: FxHashMap::default(), 130 field_resolutions: FxHashMap::default(),
131 assoc_resolutions: FxHashMap::default(),
113 type_of_expr: ArenaMap::default(), 132 type_of_expr: ArenaMap::default(),
114 type_of_pat: ArenaMap::default(), 133 type_of_pat: ArenaMap::default(),
115 var_unification_table: InPlaceUnificationTable::new(), 134 var_unification_table: InPlaceUnificationTable::new(),
@@ -135,6 +154,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
135 InferenceResult { 154 InferenceResult {
136 method_resolutions: self.method_resolutions, 155 method_resolutions: self.method_resolutions,
137 field_resolutions: self.field_resolutions, 156 field_resolutions: self.field_resolutions,
157 assoc_resolutions: self.assoc_resolutions,
138 type_of_expr: expr_types, 158 type_of_expr: expr_types,
139 type_of_pat: pat_types, 159 type_of_pat: pat_types,
140 } 160 }
@@ -152,6 +172,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
152 self.field_resolutions.insert(expr, field); 172 self.field_resolutions.insert(expr, field);
153 } 173 }
154 174
175 fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: ImplItem) {
176 self.assoc_resolutions.insert(id, item);
177 }
178
155 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { 179 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
156 self.type_of_pat.insert(pat, ty); 180 self.type_of_pat.insert(pat, ty);
157 } 181 }
@@ -341,7 +365,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
341 }) 365 })
342 } 366 }
343 367
344 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> { 368 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option<Ty> {
345 let resolved = resolver.resolve_path_segments(self.db, &path); 369 let resolved = resolver.resolve_path_segments(self.db, &path);
346 370
347 let (def, remaining_index) = resolved.into_inner(); 371 let (def, remaining_index) = resolved.into_inner();
@@ -393,26 +417,38 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
393 // Attempt to find an impl_item for the type which has a name matching 417 // Attempt to find an impl_item for the type which has a name matching
394 // the current segment 418 // the current segment
395 log::debug!("looking for path segment: {:?}", segment); 419 log::debug!("looking for path segment: {:?}", segment);
396 let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| match item { 420 let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| {
397 crate::ImplItem::Method(func) => { 421 let matching_def: Option<crate::ModuleDef> = match item {
398 let sig = func.signature(self.db); 422 crate::ImplItem::Method(func) => {
399 if segment.name == *sig.name() { 423 let sig = func.signature(self.db);
400 return Some(func.into()); 424 if segment.name == *sig.name() {
425 Some(func.into())
426 } else {
427 None
428 }
401 } 429 }
402 None
403 }
404 430
405 crate::ImplItem::Const(konst) => { 431 crate::ImplItem::Const(konst) => {
406 let sig = konst.signature(self.db); 432 let sig = konst.signature(self.db);
407 if segment.name == *sig.name() { 433 if segment.name == *sig.name() {
408 return Some(konst.into()); 434 Some(konst.into())
435 } else {
436 None
437 }
409 } 438 }
410 None
411 }
412 439
413 // TODO: Resolve associated types 440 // TODO: Resolve associated types
414 crate::ImplItem::TypeAlias(_) => None, 441 crate::ImplItem::TypeAlias(_) => None,
442 };
443 match matching_def {
444 Some(_) => {
445 self.write_assoc_resolution(id, item);
446 return matching_def;
447 }
448 None => None,
449 }
415 })?; 450 })?;
451
416 resolved = Resolution::Def(item.into()); 452 resolved = Resolution::Def(item.into());
417 } 453 }
418 454
@@ -420,7 +456,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
420 Resolution::Def(def) => { 456 Resolution::Def(def) => {
421 let typable: Option<TypableDef> = def.into(); 457 let typable: Option<TypableDef> = def.into();
422 let typable = typable?; 458 let typable = typable?;
423
424 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 459 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
425 let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs); 460 let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs);
426 let ty = self.insert_type_vars(ty); 461 let ty = self.insert_type_vars(ty);
@@ -572,7 +607,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
572 Pat::Path(path) => { 607 Pat::Path(path) => {
573 // TODO use correct resolver for the surrounding expression 608 // TODO use correct resolver for the surrounding expression
574 let resolver = self.resolver.clone(); 609 let resolver = self.resolver.clone();
575 self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown) 610 self.infer_path_expr(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown)
576 } 611 }
577 Pat::Bind { mode, name: _name, subpat } => { 612 Pat::Bind { mode, name: _name, subpat } => {
578 let inner_ty = if let Some(subpat) = subpat { 613 let inner_ty = if let Some(subpat) = subpat {
@@ -782,7 +817,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
782 Expr::Path(p) => { 817 Expr::Path(p) => {
783 // TODO this could be more efficient... 818 // TODO this could be more efficient...
784 let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); 819 let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr);
785 self.infer_path_expr(&resolver, p).unwrap_or(Ty::Unknown) 820 self.infer_path_expr(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown)
786 } 821 }
787 Expr::Continue => Ty::Never, 822 Expr::Continue => Ty::Never,
788 Expr::Break { expr } => { 823 Expr::Break { expr } => {