diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 43 |
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)] | ||
58 | enum ExprOrPatId { | ||
59 | Expr(ExprId), | ||
60 | Pat(PatId), | ||
61 | } | ||
62 | |||
63 | impl From<ExprId> for ExprOrPatId { | ||
64 | fn from(id: ExprId) -> Self { | ||
65 | ExprOrPatId::Expr(id) | ||
66 | } | ||
67 | } | ||
68 | |||
69 | impl 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)] |
59 | pub struct InferenceResult { | 77 | pub 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 | ||
77 | impl Index<ExprId> for InferenceResult { | 100 | impl 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 } => { |