aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-02-22 19:58:22 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-02-22 19:58:22 +0000
commit3d8a0982a12f3aa4b8c193a841f864b15c3cb66e (patch)
treee20ae00628cc28417e22621f583ba6988677ffcd /crates/ra_hir/src/ty.rs
parentbb665a70627cbc2f4fb930fefb04899941b6afa6 (diff)
parent247d1c17b385ff8a8c1dda2e899495146b643b98 (diff)
Merge #866
866: Implement basic support for Associated Methods r=flodiebold a=vipentti This is my attempt at learning to understand how the type inference works by adding basic support for associated methods. Currently it does not resolve associated types or constants. The basic idea is that `Resolver::resolve_path` returns a new `PathResult` type, which has two variants, `FullyResolved` and `PartiallyResolved`, fully resolved matches the previous behavior, where as `PartiallyResolved` contains the `PerNs<Resolution` in addition to a `segment_index` which contains the index of the segment which we failed to resolve. This index can then be used to continue inference in `infer_path_expr` using the `Type` we managed to resolve. This changes some of the previous apis, so looking for feedback and suggestions. This should enable fixing #832 Co-authored-by: Ville Penttinen <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs52
1 files changed, 46 insertions, 6 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 1a3e1994f..ae595c16d 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -37,7 +37,7 @@ use crate::{
37 FnSignature, ModuleDef, AdtDef, 37 FnSignature, ModuleDef, AdtDef,
38 HirDatabase, 38 HirDatabase,
39 type_ref::{TypeRef, Mutability}, 39 type_ref::{TypeRef, Mutability},
40 name::KnownName, 40 name::{KnownName},
41 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, 41 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self},
42 generics::GenericParams, 42 generics::GenericParams,
43 path::{ GenericArgs, GenericArg}, 43 path::{ GenericArgs, GenericArg},
@@ -1166,15 +1166,55 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1166 } 1166 }
1167 1167
1168 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> { 1168 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> {
1169 let resolved = resolver.resolve_path(self.db, &path).take_values()?; 1169 let resolved = resolver.resolve_path_segments(self.db, &path);
1170
1171 let (def, remaining_index) = resolved.into_inner();
1172
1173 // if the remaining_index is None, we expect the path
1174 // to be fully resolved, in this case we continue with
1175 // the default by attempting to `take_values´ from the resolution.
1176 // Otherwise the path was partially resolved, which means
1177 // we might have resolved into a type for which
1178 // we may find some associated item starting at the
1179 // path.segment pointed to by `remaining_index´
1180 let resolved =
1181 if remaining_index.is_none() { def.take_values()? } else { def.take_types()? };
1182
1170 match resolved { 1183 match resolved {
1171 Resolution::Def(def) => { 1184 Resolution::Def(def) => {
1172 let typable: Option<TypableDef> = def.into(); 1185 let typable: Option<TypableDef> = def.into();
1173 let typable = typable?; 1186 let typable = typable?;
1174 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 1187
1175 let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs); 1188 if let Some(remaining_index) = remaining_index {
1176 let ty = self.insert_type_vars(ty); 1189 let ty = self.db.type_for_def(typable, Namespace::Types);
1177 Some(ty) 1190 // TODO: Keep resolving the segments
1191 // if we have more segments to process
1192 let segment = &path.segments[remaining_index];
1193
1194 // Attempt to find an impl_item for the type which has a name matching
1195 // the current segment
1196 let ty = ty.iterate_impl_items(self.db, |item| match item {
1197 crate::ImplItem::Method(func) => {
1198 let sig = func.signature(self.db);
1199 if segment.name == *sig.name() {
1200 return Some(type_for_fn(self.db, func));
1201 }
1202 None
1203 }
1204
1205 // TODO: Resolve associated const
1206 crate::ImplItem::Const(_) => None,
1207
1208 // TODO: Resolve associated types
1209 crate::ImplItem::Type(_) => None,
1210 });
1211 ty
1212 } else {
1213 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
1214 let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs);
1215 let ty = self.insert_type_vars(ty);
1216 Some(ty)
1217 }
1178 } 1218 }
1179 Resolution::LocalBinding(pat) => { 1219 Resolution::LocalBinding(pat) => {
1180 let ty = self.type_of_pat.get(pat)?; 1220 let ty = self.type_of_pat.get(pat)?;