diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 96 |
1 files changed, 75 insertions, 21 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 562ad1f49..fb98ac907 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -42,7 +42,7 @@ use crate::{ | |||
42 | generics::GenericParams, | 42 | generics::GenericParams, |
43 | path::GenericArg, | 43 | path::GenericArg, |
44 | adt::VariantDef, | 44 | adt::VariantDef, |
45 | resolve::{Resolver, Resolution}, | 45 | resolve::{Resolver, Resolution}, nameres::Namespace |
46 | }; | 46 | }; |
47 | 47 | ||
48 | /// The ID of a type variable. | 48 | /// The ID of a type variable. |
@@ -226,6 +226,8 @@ pub enum Ty { | |||
226 | /// function has a unique type, which is output (for a function | 226 | /// function has a unique type, which is output (for a function |
227 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | 227 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. |
228 | /// | 228 | /// |
229 | /// This includes tuple struct / enum variant constructors as well. | ||
230 | /// | ||
229 | /// For example the type of `bar` here: | 231 | /// For example the type of `bar` here: |
230 | /// | 232 | /// |
231 | /// ```rust | 233 | /// ```rust |
@@ -233,8 +235,8 @@ pub enum Ty { | |||
233 | /// let bar = foo; // bar: fn() -> i32 {foo} | 235 | /// let bar = foo; // bar: fn() -> i32 {foo} |
234 | /// ``` | 236 | /// ``` |
235 | FnDef { | 237 | FnDef { |
236 | // Function definition | 238 | /// The definition of the function / constructor. |
237 | def: Function, | 239 | def: CallableDef, |
238 | /// For display | 240 | /// For display |
239 | name: Name, | 241 | name: Name, |
240 | /// Parameters and return type | 242 | /// Parameters and return type |
@@ -396,7 +398,7 @@ impl Ty { | |||
396 | None => return Ty::Unknown, | 398 | None => return Ty::Unknown, |
397 | Some(it) => it, | 399 | Some(it) => it, |
398 | }; | 400 | }; |
399 | let ty = db.type_for_def(typable); | 401 | let ty = db.type_for_def(typable, Namespace::Types); |
400 | let substs = Ty::substs_from_path(db, resolver, path, typable); | 402 | let substs = Ty::substs_from_path(db, resolver, path, typable); |
401 | ty.apply_substs(substs) | 403 | ty.apply_substs(substs) |
402 | } | 404 | } |
@@ -673,7 +675,47 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | |||
673 | let output = Ty::from_hir(db, &resolver, signature.ret_type()); | 675 | let output = Ty::from_hir(db, &resolver, signature.ret_type()); |
674 | let sig = Arc::new(FnSig { input, output }); | 676 | let sig = Arc::new(FnSig { input, output }); |
675 | let substs = make_substs(&generics); | 677 | let substs = make_substs(&generics); |
676 | Ty::FnDef { def, sig, name, substs } | 678 | Ty::FnDef { def: def.into(), sig, name, substs } |
679 | } | ||
680 | |||
681 | /// Compute the type of a tuple struct constructor. | ||
682 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | ||
683 | let var_data = def.variant_data(db); | ||
684 | let fields = match var_data.fields() { | ||
685 | Some(fields) => fields, | ||
686 | None => return type_for_struct(db, def), // Unit struct | ||
687 | }; | ||
688 | let resolver = def.resolver(db); | ||
689 | let generics = def.generic_params(db); | ||
690 | let name = def.name(db).unwrap_or_else(Name::missing); | ||
691 | let input = fields | ||
692 | .iter() | ||
693 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | ||
694 | .collect::<Vec<_>>(); | ||
695 | let output = type_for_struct(db, def); | ||
696 | let sig = Arc::new(FnSig { input, output }); | ||
697 | let substs = make_substs(&generics); | ||
698 | Ty::FnDef { def: def.into(), sig, name, substs } | ||
699 | } | ||
700 | |||
701 | /// Compute the type of a tuple enum variant constructor. | ||
702 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { | ||
703 | let var_data = def.variant_data(db); | ||
704 | let fields = match var_data.fields() { | ||
705 | Some(fields) => fields, | ||
706 | None => return type_for_enum(db, def.parent_enum(db)), // Unit variant | ||
707 | }; | ||
708 | let resolver = def.parent_enum(db).resolver(db); | ||
709 | let generics = def.parent_enum(db).generic_params(db); | ||
710 | let name = def.name(db).unwrap_or_else(Name::missing); | ||
711 | let input = fields | ||
712 | .iter() | ||
713 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | ||
714 | .collect::<Vec<_>>(); | ||
715 | let output = type_for_enum(db, def.parent_enum(db)); | ||
716 | let sig = Arc::new(FnSig { input, output }); | ||
717 | let substs = make_substs(&generics); | ||
718 | Ty::FnDef { def: def.into(), sig, name, substs } | ||
677 | } | 719 | } |
678 | 720 | ||
679 | fn make_substs(generics: &GenericParams) -> Substs { | 721 | fn make_substs(generics: &GenericParams) -> Substs { |
@@ -703,12 +745,6 @@ pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | |||
703 | } | 745 | } |
704 | } | 746 | } |
705 | 747 | ||
706 | pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> Ty { | ||
707 | let enum_parent = ev.parent_enum(db); | ||
708 | |||
709 | type_for_enum(db, enum_parent) | ||
710 | } | ||
711 | |||
712 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 748 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
713 | pub enum TypableDef { | 749 | pub enum TypableDef { |
714 | Function(Function), | 750 | Function(Function), |
@@ -735,12 +771,26 @@ impl From<ModuleDef> for Option<TypableDef> { | |||
735 | } | 771 | } |
736 | } | 772 | } |
737 | 773 | ||
738 | pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { | 774 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
739 | match def { | 775 | pub enum CallableDef { |
740 | TypableDef::Function(f) => type_for_fn(db, f), | 776 | Function(Function), |
741 | TypableDef::Struct(s) => type_for_struct(db, s), | 777 | Struct(Struct), |
742 | TypableDef::Enum(e) => type_for_enum(db, e), | 778 | EnumVariant(EnumVariant), |
743 | TypableDef::EnumVariant(v) => type_for_enum_variant(db, v), | 779 | } |
780 | impl_froms!(CallableDef: Function, Struct, EnumVariant); | ||
781 | |||
782 | pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty { | ||
783 | match (def, ns) { | ||
784 | (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f), | ||
785 | (TypableDef::Struct(s), Namespace::Types) => type_for_struct(db, s), | ||
786 | (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s), | ||
787 | (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e), | ||
788 | (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), | ||
789 | |||
790 | // 'error' cases: | ||
791 | (TypableDef::Function(_), Namespace::Types) => Ty::Unknown, | ||
792 | (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown, | ||
793 | (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown, | ||
744 | } | 794 | } |
745 | } | 795 | } |
746 | 796 | ||
@@ -1127,7 +1177,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1127 | let typable: Option<TypableDef> = def.into(); | 1177 | let typable: Option<TypableDef> = def.into(); |
1128 | let typable = typable?; | 1178 | let typable = typable?; |
1129 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | 1179 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); |
1130 | let ty = self.db.type_for_def(typable).apply_substs(substs); | 1180 | let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs); |
1131 | let ty = self.insert_type_vars(ty); | 1181 | let ty = self.insert_type_vars(ty); |
1132 | Some(ty) | 1182 | Some(ty) |
1133 | } | 1183 | } |
@@ -1178,12 +1228,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1178 | let substs = Ty::substs_from_path(self.db, resolver, path, def); | 1228 | let substs = Ty::substs_from_path(self.db, resolver, path, def); |
1179 | match def { | 1229 | match def { |
1180 | TypableDef::Struct(s) => { | 1230 | TypableDef::Struct(s) => { |
1181 | let ty = type_for_struct(self.db, s); | 1231 | let ty = s.ty(self.db); |
1182 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 1232 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
1183 | (ty, Some(s.into())) | 1233 | (ty, Some(s.into())) |
1184 | } | 1234 | } |
1185 | TypableDef::EnumVariant(var) => { | 1235 | TypableDef::EnumVariant(var) => { |
1186 | let ty = type_for_enum_variant(self.db, var); | 1236 | let ty = var.parent_enum(self.db).ty(self.db); |
1187 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 1237 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
1188 | (ty, Some(var.into())) | 1238 | (ty, Some(var.into())) |
1189 | } | 1239 | } |
@@ -1384,7 +1434,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1384 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | 1434 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { |
1385 | Some((ty, func)) => { | 1435 | Some((ty, func)) => { |
1386 | self.write_method_resolution(tgt_expr, func); | 1436 | self.write_method_resolution(tgt_expr, func); |
1387 | (ty, self.db.type_for_def(func.into()), Some(func.generic_params(self.db))) | 1437 | ( |
1438 | ty, | ||
1439 | self.db.type_for_def(func.into(), Namespace::Values), | ||
1440 | Some(func.generic_params(self.db)), | ||
1441 | ) | ||
1388 | } | 1442 | } |
1389 | None => (Ty::Unknown, receiver_ty, None), | 1443 | None => (Ty::Unknown, receiver_ty, None), |
1390 | }; | 1444 | }; |