diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 108 |
1 files changed, 83 insertions, 25 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index d4d896673..2751ab3ab 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -32,17 +32,20 @@ use rustc_hash::FxHashMap; | |||
32 | 32 | ||
33 | use test_utils::tested_by; | 33 | use test_utils::tested_by; |
34 | 34 | ||
35 | use ra_syntax::ast::NameOwner; | ||
36 | |||
35 | use crate::{ | 37 | use crate::{ |
36 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, | 38 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, |
39 | Const, | ||
37 | FnSignature, ModuleDef, AdtDef, | 40 | FnSignature, ModuleDef, AdtDef, |
38 | HirDatabase, | 41 | HirDatabase, |
39 | type_ref::{TypeRef, Mutability}, | 42 | type_ref::{TypeRef, Mutability}, |
40 | name::KnownName, | 43 | name::{KnownName, AsName}, |
41 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, | 44 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, |
42 | generics::GenericParams, | 45 | generics::GenericParams, |
43 | path::GenericArg, | 46 | path::GenericArg, |
44 | adt::VariantDef, | 47 | adt::VariantDef, |
45 | resolve::{Resolver, Resolution}, nameres::Namespace | 48 | resolve::{Resolver, Resolution, PathResult}, nameres::Namespace |
46 | }; | 49 | }; |
47 | 50 | ||
48 | /// The ID of a type variable. | 51 | /// The ID of a type variable. |
@@ -370,7 +373,7 @@ impl Ty { | |||
370 | } | 373 | } |
371 | 374 | ||
372 | // Resolve the path (in type namespace) | 375 | // Resolve the path (in type namespace) |
373 | let resolution = resolver.resolve_path(db, path).take_types(); | 376 | let resolution = resolver.resolve_path(db, path).into_per_ns().take_types(); |
374 | 377 | ||
375 | let def = match resolution { | 378 | let def = match resolution { |
376 | Some(Resolution::Def(def)) => def, | 379 | Some(Resolution::Def(def)) => def, |
@@ -678,6 +681,19 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | |||
678 | Ty::FnDef { def: def.into(), sig, name, substs } | 681 | Ty::FnDef { def: def.into(), sig, name, substs } |
679 | } | 682 | } |
680 | 683 | ||
684 | fn type_for_const(db: &impl HirDatabase, resolver: &Resolver, def: Const) -> Ty { | ||
685 | let node = def.source(db).1; | ||
686 | |||
687 | let tr = node | ||
688 | .type_ref() | ||
689 | .map(TypeRef::from_ast) | ||
690 | .as_ref() | ||
691 | .map(|tr| Ty::from_hir(db, resolver, tr)) | ||
692 | .unwrap_or_else(|| Ty::Unknown); | ||
693 | |||
694 | tr | ||
695 | } | ||
696 | |||
681 | /// Compute the type of a tuple struct constructor. | 697 | /// Compute the type of a tuple struct constructor. |
682 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | 698 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { |
683 | let var_data = def.variant_data(db); | 699 | let var_data = def.variant_data(db); |
@@ -1172,15 +1188,56 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1172 | } | 1188 | } |
1173 | 1189 | ||
1174 | fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> { | 1190 | fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> { |
1175 | let resolved = resolver.resolve_path(self.db, &path).take_values()?; | 1191 | let resolved = resolver.resolve_path(self.db, &path); |
1192 | |||
1193 | let (resolved, segment_index) = match resolved { | ||
1194 | PathResult::FullyResolved(def) => (def.take_values()?, None), | ||
1195 | PathResult::PartiallyResolved(def, index) => (def.take_types()?, Some(index)), | ||
1196 | }; | ||
1197 | |||
1176 | match resolved { | 1198 | match resolved { |
1177 | Resolution::Def(def) => { | 1199 | Resolution::Def(def) => { |
1178 | let typable: Option<TypableDef> = def.into(); | 1200 | let typable: Option<TypableDef> = def.into(); |
1179 | let typable = typable?; | 1201 | let typable = typable?; |
1180 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | 1202 | |
1181 | let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs); | 1203 | if let Some(segment_index) = segment_index { |
1182 | let ty = self.insert_type_vars(ty); | 1204 | let ty = self.db.type_for_def(typable, Namespace::Types); |
1183 | Some(ty) | 1205 | // TODO: What to do if segment_index is not the last segment |
1206 | // in the path | ||
1207 | let segment = &path.segments[segment_index]; | ||
1208 | |||
1209 | // Attempt to find an impl_item for the type which has a name matching | ||
1210 | // the current segment | ||
1211 | let ty = ty.iterate_impl_items(self.db, |item| match item { | ||
1212 | crate::ImplItem::Method(func) => { | ||
1213 | let sig = func.signature(self.db); | ||
1214 | if segment.name == *sig.name() { | ||
1215 | return Some(type_for_fn(self.db, func)); | ||
1216 | } | ||
1217 | None | ||
1218 | } | ||
1219 | crate::ImplItem::Const(c) => { | ||
1220 | let node = c.source(self.db).1; | ||
1221 | |||
1222 | if let Some(name) = node.name().map(|n| n.as_name()) { | ||
1223 | if segment.name == name { | ||
1224 | return Some(type_for_const(self.db, resolver, c)); | ||
1225 | } | ||
1226 | } | ||
1227 | |||
1228 | None | ||
1229 | } | ||
1230 | |||
1231 | // TODO: Resolve associated types | ||
1232 | crate::ImplItem::Type(_) => None, | ||
1233 | }); | ||
1234 | ty | ||
1235 | } else { | ||
1236 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | ||
1237 | let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs); | ||
1238 | let ty = self.insert_type_vars(ty); | ||
1239 | Some(ty) | ||
1240 | } | ||
1184 | } | 1241 | } |
1185 | Resolution::LocalBinding(pat) => { | 1242 | Resolution::LocalBinding(pat) => { |
1186 | let ty = self.type_of_pat.get(pat)?; | 1243 | let ty = self.type_of_pat.get(pat)?; |
@@ -1204,23 +1261,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1204 | None => return (Ty::Unknown, None), | 1261 | None => return (Ty::Unknown, None), |
1205 | }; | 1262 | }; |
1206 | let resolver = &self.resolver; | 1263 | let resolver = &self.resolver; |
1207 | let typable: Option<TypableDef> = match resolver.resolve_path(self.db, &path).take_types() { | 1264 | let typable: Option<TypableDef> = |
1208 | Some(Resolution::Def(def)) => def.into(), | 1265 | match resolver.resolve_path(self.db, &path).into_per_ns().take_types() { |
1209 | Some(Resolution::LocalBinding(..)) => { | 1266 | Some(Resolution::Def(def)) => def.into(), |
1210 | // this cannot happen | 1267 | Some(Resolution::LocalBinding(..)) => { |
1211 | log::error!("path resolved to local binding in type ns"); | 1268 | // this cannot happen |
1212 | return (Ty::Unknown, None); | 1269 | log::error!("path resolved to local binding in type ns"); |
1213 | } | 1270 | return (Ty::Unknown, None); |
1214 | Some(Resolution::GenericParam(..)) => { | 1271 | } |
1215 | // generic params can't be used in struct literals | 1272 | Some(Resolution::GenericParam(..)) => { |
1216 | return (Ty::Unknown, None); | 1273 | // generic params can't be used in struct literals |
1217 | } | 1274 | return (Ty::Unknown, None); |
1218 | Some(Resolution::SelfType(..)) => { | 1275 | } |
1219 | // TODO this is allowed in an impl for a struct, handle this | 1276 | Some(Resolution::SelfType(..)) => { |
1220 | return (Ty::Unknown, None); | 1277 | // TODO this is allowed in an impl for a struct, handle this |
1221 | } | 1278 | return (Ty::Unknown, None); |
1222 | None => return (Ty::Unknown, None), | 1279 | } |
1223 | }; | 1280 | None => return (Ty::Unknown, None), |
1281 | }; | ||
1224 | let def = match typable { | 1282 | let def = match typable { |
1225 | None => return (Ty::Unknown, None), | 1283 | None => return (Ty::Unknown, None), |
1226 | Some(it) => it, | 1284 | Some(it) => it, |