aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/ty/infer.rs43
1 files changed, 40 insertions, 3 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 5e4d49ffb..f7a35f05b 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -54,6 +54,24 @@ pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> {
54 Arc::new(ctx.resolve_all()) 54 Arc::new(ctx.resolve_all())
55} 55}
56 56
57#[derive(Debug, Copy, Clone)]
58enum ExprOrPatId {
59 Expr(ExprId),
60 Pat(PatId),
61}
62
63impl From<ExprId> for ExprOrPatId {
64 fn from(id: ExprId) -> Self {
65 ExprOrPatId::Expr(id)
66 }
67}
68
69impl From<PatId> for ExprOrPatId {
70 fn from(id: PatId) -> Self {
71 ExprOrPatId::Pat(id)
72 }
73}
74
57/// The result of type inference: A mapping from expressions and patterns to types. 75/// The result of type inference: A mapping from expressions and patterns to types.
58#[derive(Clone, PartialEq, Eq, Debug)] 76#[derive(Clone, PartialEq, Eq, Debug)]
59pub struct InferenceResult { 77pub struct InferenceResult {
@@ -61,6 +79,8 @@ pub struct InferenceResult {
61 method_resolutions: FxHashMap<ExprId, Function>, 79 method_resolutions: FxHashMap<ExprId, Function>,
62 /// For each field access expr, records the field it resolves to. 80 /// For each field access expr, records the field it resolves to.
63 field_resolutions: FxHashMap<ExprId, StructField>, 81 field_resolutions: FxHashMap<ExprId, StructField>,
82 /// For each associated function call expr, records the function it resolves to
83 assoc_fn_resolutions: FxHashMap<ExprId, Function>,
64 pub(super) type_of_expr: ArenaMap<ExprId, Ty>, 84 pub(super) type_of_expr: ArenaMap<ExprId, Ty>,
65 pub(super) type_of_pat: ArenaMap<PatId, Ty>, 85 pub(super) type_of_pat: ArenaMap<PatId, Ty>,
66} 86}
@@ -72,6 +92,9 @@ impl InferenceResult {
72 pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> { 92 pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> {
73 self.field_resolutions.get(&expr).map(|it| *it) 93 self.field_resolutions.get(&expr).map(|it| *it)
74 } 94 }
95 pub fn assoc_fn_resolutions(&self, expr: ExprId) -> Option<Function> {
96 self.assoc_fn_resolutions.get(&expr).map(|it| *it)
97 }
75} 98}
76 99
77impl Index<ExprId> for InferenceResult { 100impl Index<ExprId> for InferenceResult {
@@ -99,6 +122,7 @@ struct InferenceContext<'a, D: HirDatabase> {
99 var_unification_table: InPlaceUnificationTable<TypeVarId>, 122 var_unification_table: InPlaceUnificationTable<TypeVarId>,
100 method_resolutions: FxHashMap<ExprId, Function>, 123 method_resolutions: FxHashMap<ExprId, Function>,
101 field_resolutions: FxHashMap<ExprId, StructField>, 124 field_resolutions: FxHashMap<ExprId, StructField>,
125 assoc_fn_resolutions: FxHashMap<ExprId, Function>,
102 type_of_expr: ArenaMap<ExprId, Ty>, 126 type_of_expr: ArenaMap<ExprId, Ty>,
103 type_of_pat: ArenaMap<PatId, Ty>, 127 type_of_pat: ArenaMap<PatId, Ty>,
104 /// The return type of the function being inferred. 128 /// The return type of the function being inferred.
@@ -110,6 +134,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
110 InferenceContext { 134 InferenceContext {
111 method_resolutions: FxHashMap::default(), 135 method_resolutions: FxHashMap::default(),
112 field_resolutions: FxHashMap::default(), 136 field_resolutions: FxHashMap::default(),
137 assoc_fn_resolutions: FxHashMap::default(),
113 type_of_expr: ArenaMap::default(), 138 type_of_expr: ArenaMap::default(),
114 type_of_pat: ArenaMap::default(), 139 type_of_pat: ArenaMap::default(),
115 var_unification_table: InPlaceUnificationTable::new(), 140 var_unification_table: InPlaceUnificationTable::new(),
@@ -135,6 +160,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
135 InferenceResult { 160 InferenceResult {
136 method_resolutions: self.method_resolutions, 161 method_resolutions: self.method_resolutions,
137 field_resolutions: self.field_resolutions, 162 field_resolutions: self.field_resolutions,
163 assoc_fn_resolutions: self.assoc_fn_resolutions,
138 type_of_expr: expr_types, 164 type_of_expr: expr_types,
139 type_of_pat: pat_types, 165 type_of_pat: pat_types,
140 } 166 }
@@ -152,6 +178,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
152 self.field_resolutions.insert(expr, field); 178 self.field_resolutions.insert(expr, field);
153 } 179 }
154 180
181 fn write_assoc_fn_resolution(&mut self, expr: ExprId, func: Function) {
182 self.assoc_fn_resolutions.insert(expr, func);
183 }
184
155 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { 185 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
156 self.type_of_pat.insert(pat, ty); 186 self.type_of_pat.insert(pat, ty);
157 } 187 }
@@ -341,7 +371,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
341 }) 371 })
342 } 372 }
343 373
344 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> { 374 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option<Ty> {
345 let resolved = resolver.resolve_path_segments(self.db, &path); 375 let resolved = resolver.resolve_path_segments(self.db, &path);
346 376
347 let (def, remaining_index) = resolved.into_inner(); 377 let (def, remaining_index) = resolved.into_inner();
@@ -421,6 +451,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
421 let typable: Option<TypableDef> = def.into(); 451 let typable: Option<TypableDef> = def.into();
422 let typable = typable?; 452 let typable = typable?;
423 453
454 if let ExprOrPatId::Expr(expr) = id {
455 match typable {
456 TypableDef::Function(func) => self.write_assoc_fn_resolution(expr, func),
457 _ => {}
458 };
459 }
460
424 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 461 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); 462 let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs);
426 let ty = self.insert_type_vars(ty); 463 let ty = self.insert_type_vars(ty);
@@ -572,7 +609,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
572 Pat::Path(path) => { 609 Pat::Path(path) => {
573 // TODO use correct resolver for the surrounding expression 610 // TODO use correct resolver for the surrounding expression
574 let resolver = self.resolver.clone(); 611 let resolver = self.resolver.clone();
575 self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown) 612 self.infer_path_expr(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown)
576 } 613 }
577 Pat::Bind { mode, name: _name, subpat } => { 614 Pat::Bind { mode, name: _name, subpat } => {
578 let inner_ty = if let Some(subpat) = subpat { 615 let inner_ty = if let Some(subpat) = subpat {
@@ -782,7 +819,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
782 Expr::Path(p) => { 819 Expr::Path(p) => {
783 // TODO this could be more efficient... 820 // TODO this could be more efficient...
784 let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); 821 let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr);
785 self.infer_path_expr(&resolver, p).unwrap_or(Ty::Unknown) 822 self.infer_path_expr(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown)
786 } 823 }
787 Expr::Continue => Ty::Never, 824 Expr::Continue => Ty::Never,
788 Expr::Break { expr } => { 825 Expr::Break { expr } => {