diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 150 |
1 files changed, 106 insertions, 44 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index f9cdbcab3..fc699a2ae 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -32,7 +32,7 @@ use rustc_hash::FxHashMap; | |||
32 | 32 | ||
33 | use crate::{ | 33 | use crate::{ |
34 | Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, | 34 | Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, |
35 | FnSignature, FnScopes, ModuleDef, | 35 | FnSignature, FnScopes, ModuleDef, Crate, |
36 | db::HirDatabase, | 36 | db::HirDatabase, |
37 | type_ref::{TypeRef, Mutability}, | 37 | type_ref::{TypeRef, Mutability}, |
38 | name::KnownName, | 38 | name::KnownName, |
@@ -163,6 +163,33 @@ impl Substs { | |||
163 | } | 163 | } |
164 | } | 164 | } |
165 | 165 | ||
166 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
167 | pub enum AdtDef { | ||
168 | Struct(Struct), | ||
169 | Def(DefId), // Enum | ||
170 | } | ||
171 | |||
172 | impl From<Struct> for AdtDef { | ||
173 | fn from(struct_: Struct) -> AdtDef { | ||
174 | AdtDef::Struct(struct_) | ||
175 | } | ||
176 | } | ||
177 | |||
178 | impl From<DefId> for AdtDef { | ||
179 | fn from(def_id: DefId) -> AdtDef { | ||
180 | AdtDef::Def(def_id) | ||
181 | } | ||
182 | } | ||
183 | |||
184 | impl AdtDef { | ||
185 | fn krate(self, db: &impl HirDatabase) -> Option<Crate> { | ||
186 | match self { | ||
187 | AdtDef::Struct(s) => s.module(db).krate(db), | ||
188 | AdtDef::Def(def_id) => def_id.krate(db), | ||
189 | } | ||
190 | } | ||
191 | } | ||
192 | |||
166 | /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). | 193 | /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). |
167 | /// | 194 | /// |
168 | /// This should be cheap to clone. | 195 | /// This should be cheap to clone. |
@@ -184,7 +211,7 @@ pub enum Ty { | |||
184 | /// Structures, enumerations and unions. | 211 | /// Structures, enumerations and unions. |
185 | Adt { | 212 | Adt { |
186 | /// The DefId of the struct/enum. | 213 | /// The DefId of the struct/enum. |
187 | def_id: DefId, | 214 | def_id: AdtDef, |
188 | /// The name, for displaying. | 215 | /// The name, for displaying. |
189 | name: Name, | 216 | name: Name, |
190 | /// Substitutions for the generic parameters of the type. | 217 | /// Substitutions for the generic parameters of the type. |
@@ -384,6 +411,7 @@ impl Ty { | |||
384 | let resolved = match module.resolve_path(db, path).take_types() { | 411 | let resolved = match module.resolve_path(db, path).take_types() { |
385 | Some(ModuleDef::Def(r)) => r.into(), | 412 | Some(ModuleDef::Def(r)) => r.into(), |
386 | Some(ModuleDef::Function(f)) => f.into(), | 413 | Some(ModuleDef::Function(f)) => f.into(), |
414 | Some(ModuleDef::Struct(s)) => s.into(), | ||
387 | None | Some(ModuleDef::Module(_)) => return Ty::Unknown, | 415 | None | Some(ModuleDef::Module(_)) => return Ty::Unknown, |
388 | }; | 416 | }; |
389 | let ty = db.type_for_def(resolved); | 417 | let ty = db.type_for_def(resolved); |
@@ -409,6 +437,7 @@ impl Ty { | |||
409 | .expect("path should have at least one segment"); | 437 | .expect("path should have at least one segment"); |
410 | let (def_generics, segment) = match resolved { | 438 | let (def_generics, segment) = match resolved { |
411 | TypableDef::Function(func) => (func.generic_params(db), last), | 439 | TypableDef::Function(func) => (func.generic_params(db), last), |
440 | TypableDef::Struct(s) => (s.generic_params(db), last), | ||
412 | TypableDef::Def(def_id) => match def_id.resolve(db) { | 441 | TypableDef::Def(def_id) => match def_id.resolve(db) { |
413 | Def::Struct(s) => (s.generic_params(db), last), | 442 | Def::Struct(s) => (s.generic_params(db), last), |
414 | Def::Enum(e) => (e.generic_params(db), last), | 443 | Def::Enum(e) => (e.generic_params(db), last), |
@@ -642,7 +671,7 @@ fn make_substs(generics: &GenericParams) -> Substs { | |||
642 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 671 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { |
643 | let generics = s.generic_params(db); | 672 | let generics = s.generic_params(db); |
644 | Ty::Adt { | 673 | Ty::Adt { |
645 | def_id: s.def_id(), | 674 | def_id: s.into(), |
646 | name: s.name(db).unwrap_or_else(Name::missing), | 675 | name: s.name(db).unwrap_or_else(Name::missing), |
647 | substs: make_substs(&generics), | 676 | substs: make_substs(&generics), |
648 | } | 677 | } |
@@ -651,7 +680,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | |||
651 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | 680 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { |
652 | let generics = s.generic_params(db); | 681 | let generics = s.generic_params(db); |
653 | Ty::Adt { | 682 | Ty::Adt { |
654 | def_id: s.def_id(), | 683 | def_id: s.def_id().into(), |
655 | name: s.name(db).unwrap_or_else(Name::missing), | 684 | name: s.name(db).unwrap_or_else(Name::missing), |
656 | substs: make_substs(&generics), | 685 | substs: make_substs(&generics), |
657 | } | 686 | } |
@@ -666,6 +695,7 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T | |||
666 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 695 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
667 | pub enum TypableDef { | 696 | pub enum TypableDef { |
668 | Function(Function), | 697 | Function(Function), |
698 | Struct(Struct), | ||
669 | Def(DefId), | 699 | Def(DefId), |
670 | } | 700 | } |
671 | 701 | ||
@@ -675,6 +705,12 @@ impl From<Function> for TypableDef { | |||
675 | } | 705 | } |
676 | } | 706 | } |
677 | 707 | ||
708 | impl From<Struct> for TypableDef { | ||
709 | fn from(struct_: Struct) -> TypableDef { | ||
710 | TypableDef::Struct(struct_) | ||
711 | } | ||
712 | } | ||
713 | |||
678 | impl From<DefId> for TypableDef { | 714 | impl From<DefId> for TypableDef { |
679 | fn from(func: DefId) -> TypableDef { | 715 | fn from(func: DefId) -> TypableDef { |
680 | TypableDef::Def(func) | 716 | TypableDef::Def(func) |
@@ -684,8 +720,8 @@ impl From<DefId> for TypableDef { | |||
684 | pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { | 720 | pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { |
685 | match def { | 721 | match def { |
686 | TypableDef::Function(f) => type_for_fn(db, f), | 722 | TypableDef::Function(f) => type_for_fn(db, f), |
723 | TypableDef::Struct(s) => type_for_struct(db, s), | ||
687 | TypableDef::Def(def_id) => match def_id.resolve(db) { | 724 | TypableDef::Def(def_id) => match def_id.resolve(db) { |
688 | Def::Struct(s) => type_for_struct(db, s), | ||
689 | Def::Enum(e) => type_for_enum(db, e), | 725 | Def::Enum(e) => type_for_enum(db, e), |
690 | Def::EnumVariant(ev) => type_for_enum_variant(db, ev), | 726 | Def::EnumVariant(ev) => type_for_enum_variant(db, ev), |
691 | _ => { | 727 | _ => { |
@@ -700,22 +736,44 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { | |||
700 | } | 736 | } |
701 | } | 737 | } |
702 | 738 | ||
703 | pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> { | 739 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
704 | let def = def_id.resolve(db); | 740 | pub enum VariantDef { |
705 | let (variant_data, generics) = match def { | 741 | Struct(Struct), |
706 | Def::Struct(s) => (s.variant_data(db), s.generic_params(db)), | 742 | Def(DefId), // EnumVariant |
707 | Def::EnumVariant(ev) => (ev.variant_data(db), ev.parent_enum(db).generic_params(db)), | 743 | } |
708 | // TODO: unions | 744 | |
709 | Def::Enum(_) => { | 745 | impl From<Struct> for VariantDef { |
710 | // this can happen in (invalid) code, but enums don't have fields themselves | 746 | fn from(struct_: Struct) -> VariantDef { |
711 | return None; | 747 | VariantDef::Struct(struct_) |
712 | } | 748 | } |
713 | _ => panic!( | 749 | } |
714 | "trying to get type for field {:?} in non-struct/variant {:?}", | 750 | |
715 | field, def_id | 751 | impl From<DefId> for VariantDef { |
716 | ), | 752 | fn from(def_id: DefId) -> VariantDef { |
753 | VariantDef::Def(def_id) | ||
754 | } | ||
755 | } | ||
756 | |||
757 | pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option<Ty> { | ||
758 | let (variant_data, generics, module) = match def { | ||
759 | VariantDef::Struct(s) => (s.variant_data(db), s.generic_params(db), s.module(db)), | ||
760 | VariantDef::Def(def_id) => match def_id.resolve(db) { | ||
761 | Def::EnumVariant(ev) => ( | ||
762 | ev.variant_data(db), | ||
763 | ev.parent_enum(db).generic_params(db), | ||
764 | def_id.module(db), | ||
765 | ), | ||
766 | // TODO: unions | ||
767 | Def::Enum(_) => { | ||
768 | // this can happen in (invalid) code, but enums don't have fields themselves | ||
769 | return None; | ||
770 | } | ||
771 | _ => panic!( | ||
772 | "trying to get type for field {:?} in non-struct/variant {:?}", | ||
773 | field, def_id | ||
774 | ), | ||
775 | }, | ||
717 | }; | 776 | }; |
718 | let module = def_id.module(db); | ||
719 | // We can't have an impl block ere, right? | 777 | // We can't have an impl block ere, right? |
720 | // let impl_block = def_id.impl_block(db); | 778 | // let impl_block = def_id.impl_block(db); |
721 | let type_ref = variant_data.get_field_type_ref(&field)?; | 779 | let type_ref = variant_data.get_field_type_ref(&field)?; |
@@ -1076,17 +1134,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1076 | }; | 1134 | }; |
1077 | 1135 | ||
1078 | // resolve in module | 1136 | // resolve in module |
1079 | let resolved = match self.module.resolve_path(self.db, &path).take_values()? { | 1137 | let typable = match self.module.resolve_path(self.db, &path).take_values()? { |
1080 | ModuleDef::Def(it) => it.into(), | 1138 | ModuleDef::Def(it) => it.into(), |
1081 | ModuleDef::Function(func) => func.into(), | 1139 | ModuleDef::Function(func) => func.into(), |
1140 | ModuleDef::Struct(s) => s.into(), | ||
1082 | ModuleDef::Module(_) => return None, | 1141 | ModuleDef::Module(_) => return None, |
1083 | }; | 1142 | }; |
1084 | let ty = self.db.type_for_def(resolved); | 1143 | let ty = self.db.type_for_def(typable); |
1085 | let ty = self.insert_type_vars(ty); | 1144 | let ty = self.insert_type_vars(ty); |
1086 | Some(ty) | 1145 | Some(ty) |
1087 | } | 1146 | } |
1088 | 1147 | ||
1089 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) { | 1148 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { |
1090 | let path = match path { | 1149 | let path = match path { |
1091 | Some(path) => path, | 1150 | Some(path) => path, |
1092 | None => return (Ty::Unknown, None), | 1151 | None => return (Ty::Unknown, None), |
@@ -1094,7 +1153,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1094 | let def = match self.module.resolve_path(self.db, &path).take_types() { | 1153 | let def = match self.module.resolve_path(self.db, &path).take_types() { |
1095 | Some(ModuleDef::Def(def_id)) => def_id.into(), | 1154 | Some(ModuleDef::Def(def_id)) => def_id.into(), |
1096 | Some(ModuleDef::Function(func)) => func.into(), | 1155 | Some(ModuleDef::Function(func)) => func.into(), |
1097 | _ => return (Ty::Unknown, None), | 1156 | Some(ModuleDef::Struct(s)) => s.into(), |
1157 | None | Some(ModuleDef::Module(_)) => return (Ty::Unknown, None), | ||
1098 | }; | 1158 | }; |
1099 | // TODO remove the duplication between here and `Ty::from_path`? | 1159 | // TODO remove the duplication between here and `Ty::from_path`? |
1100 | // TODO provide generics of function | 1160 | // TODO provide generics of function |
@@ -1109,37 +1169,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1109 | ); | 1169 | ); |
1110 | match def { | 1170 | match def { |
1111 | TypableDef::Def(def_id) => match def_id.resolve(self.db) { | 1171 | TypableDef::Def(def_id) => match def_id.resolve(self.db) { |
1112 | Def::Struct(s) => { | ||
1113 | let ty = type_for_struct(self.db, s); | ||
1114 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | ||
1115 | (ty, Some(def_id)) | ||
1116 | } | ||
1117 | Def::EnumVariant(ev) => { | 1172 | Def::EnumVariant(ev) => { |
1118 | let ty = type_for_enum_variant(self.db, ev); | 1173 | let ty = type_for_enum_variant(self.db, ev); |
1119 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 1174 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
1120 | (ty, Some(def_id)) | 1175 | (ty, Some(def_id.into())) |
1121 | } | 1176 | } |
1122 | _ => (Ty::Unknown, None), | 1177 | _ => (Ty::Unknown, None), |
1123 | }, | 1178 | }, |
1124 | TypableDef::Function(_) => (Ty::Unknown, None), | 1179 | TypableDef::Function(_) => (Ty::Unknown, None), |
1180 | TypableDef::Struct(s) => { | ||
1181 | let ty = type_for_struct(self.db, s); | ||
1182 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | ||
1183 | (ty, Some(s.into())) | ||
1184 | } | ||
1125 | } | 1185 | } |
1126 | } | 1186 | } |
1127 | 1187 | ||
1128 | fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { | 1188 | fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { |
1129 | let (ty, def_id) = self.resolve_variant(path); | 1189 | let (ty, def) = self.resolve_variant(path); |
1130 | let def_id = def_id?; | 1190 | match def? { |
1131 | let def = def_id.resolve(self.db); | 1191 | VariantDef::Struct(s) => { |
1132 | |||
1133 | match def { | ||
1134 | Def::Struct(s) => { | ||
1135 | let fields = s.fields(self.db); | 1192 | let fields = s.fields(self.db); |
1136 | Some((ty, fields)) | 1193 | Some((ty, fields)) |
1137 | } | 1194 | } |
1138 | Def::EnumVariant(ev) => { | 1195 | VariantDef::Def(def_id) => match def_id.resolve(self.db) { |
1139 | let fields = ev.fields(self.db); | 1196 | Def::EnumVariant(ev) => { |
1140 | Some((ty, fields)) | 1197 | let fields = ev.fields(self.db); |
1141 | } | 1198 | Some((ty, fields)) |
1142 | _ => None, | 1199 | } |
1200 | _ => None, | ||
1201 | }, | ||
1143 | } | 1202 | } |
1144 | } | 1203 | } |
1145 | 1204 | ||
@@ -1240,6 +1299,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1240 | .and_then(|module_def| match module_def { | 1299 | .and_then(|module_def| match module_def { |
1241 | ModuleDef::Def(it) => Some(it.into()), | 1300 | ModuleDef::Def(it) => Some(it.into()), |
1242 | ModuleDef::Function(func) => Some(func.into()), | 1301 | ModuleDef::Function(func) => Some(func.into()), |
1302 | ModuleDef::Struct(s) => Some(s.into()), | ||
1243 | ModuleDef::Module(_) => None, | 1303 | ModuleDef::Module(_) => None, |
1244 | }) | 1304 | }) |
1245 | .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), | 1305 | .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), |
@@ -1433,7 +1493,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1433 | for field in fields { | 1493 | for field in fields { |
1434 | let field_ty = if let Some(def_id) = def_id { | 1494 | let field_ty = if let Some(def_id) = def_id { |
1435 | self.db | 1495 | self.db |
1436 | .type_for_field(def_id, field.name.clone()) | 1496 | .type_for_field(def_id.into(), field.name.clone()) |
1437 | .unwrap_or(Ty::Unknown) | 1497 | .unwrap_or(Ty::Unknown) |
1438 | .subst(&substs) | 1498 | .subst(&substs) |
1439 | } else { | 1499 | } else { |
@@ -1457,10 +1517,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1457 | i.and_then(|i| fields.get(i).cloned()) | 1517 | i.and_then(|i| fields.get(i).cloned()) |
1458 | } | 1518 | } |
1459 | Ty::Adt { | 1519 | Ty::Adt { |
1460 | def_id, ref substs, .. | 1520 | def_id: AdtDef::Struct(s), |
1521 | ref substs, | ||
1522 | .. | ||
1461 | } => self | 1523 | } => self |
1462 | .db | 1524 | .db |
1463 | .type_for_field(def_id, name.clone()) | 1525 | .type_for_field(s.into(), name.clone()) |
1464 | .map(|ty| ty.subst(substs)), | 1526 | .map(|ty| ty.subst(substs)), |
1465 | _ => None, | 1527 | _ => None, |
1466 | }) | 1528 | }) |