aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-11-26 11:02:57 +0000
committerAleksey Kladov <[email protected]>2019-11-26 11:02:57 +0000
commite5eadb339039e21718d382c0b3d02a4bf053b3f4 (patch)
tree2f7839288ce5676a89c6d6062cbaf70544e0beed /crates/ra_hir/src/code_model.rs
parent5901cc736074bbc4d780a8e45079d405ab2cec4b (diff)
Introduce hir::Type
It should provide a convenient API over more low-level Ty
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r--crates/ra_hir/src/code_model.rs166
1 files changed, 159 insertions, 7 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index f7fc80d4e..a7bba85e1 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -10,9 +10,9 @@ use hir_def::{
10 docs::Documentation, 10 docs::Documentation,
11 per_ns::PerNs, 11 per_ns::PerNs,
12 resolver::{HasResolver, TypeNs}, 12 resolver::{HasResolver, TypeNs},
13 type_ref::TypeRef, 13 type_ref::{Mutability, TypeRef},
14 AstItemDef, ConstId, ContainerId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, 14 AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule,
15 LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, 15 ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId,
16 StaticId, StructId, TraitId, TypeAliasId, UnionId, 16 StaticId, StructId, TraitId, TypeAliasId, UnionId,
17}; 17};
18use hir_expand::{ 18use hir_expand::{
@@ -26,8 +26,12 @@ use ra_syntax::{ast, AstNode, SyntaxNode};
26use crate::{ 26use crate::{
27 db::{DefDatabase, HirDatabase}, 27 db::{DefDatabase, HirDatabase},
28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, 28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
29 ty::{InferenceResult, Namespace, TraitRef}, 29 ty::display::HirFormatter,
30 Either, Name, Source, Ty, 30 ty::{
31 self, InEnvironment, InferenceResult, Namespace, TraitEnvironment, TraitRef, Ty, TypeCtor,
32 TypeWalk,
33 },
34 CallableDef, Either, HirDisplay, Name, Source,
31}; 35};
32 36
33/// hir::Crate describes a single crate. It's the main interface with which 37/// hir::Crate describes a single crate. It's the main interface with which
@@ -469,6 +473,10 @@ pub enum Adt {
469impl_froms!(Adt: Struct, Union, Enum); 473impl_froms!(Adt: Struct, Union, Enum);
470 474
471impl Adt { 475impl Adt {
476 pub fn has_non_default_type_params(self, db: &impl HirDatabase) -> bool {
477 let subst = db.generic_defaults(self.into());
478 subst.iter().any(|ty| ty == &Ty::Unknown)
479 }
472 pub fn ty(self, db: &impl HirDatabase) -> Ty { 480 pub fn ty(self, db: &impl HirDatabase) -> Ty {
473 match self { 481 match self {
474 Adt::Struct(it) => it.ty(db), 482 Adt::Struct(it) => it.ty(db),
@@ -777,6 +785,11 @@ pub struct TypeAlias {
777} 785}
778 786
779impl TypeAlias { 787impl TypeAlias {
788 pub fn has_non_default_type_params(self, db: &impl HirDatabase) -> bool {
789 let subst = db.generic_defaults(self.id.into());
790 subst.iter().any(|ty| ty == &Ty::Unknown)
791 }
792
780 pub fn module(self, db: &impl DefDatabase) -> Module { 793 pub fn module(self, db: &impl DefDatabase) -> Module {
781 Module { id: self.id.lookup(db).module(db) } 794 Module { id: self.id.lookup(db).module(db) }
782 } 795 }
@@ -927,9 +940,14 @@ impl Local {
927 self.parent.module(db) 940 self.parent.module(db)
928 } 941 }
929 942
930 pub fn ty(self, db: &impl HirDatabase) -> Ty { 943 pub fn ty(self, db: &impl HirDatabase) -> Type {
931 let infer = db.infer(self.parent); 944 let infer = db.infer(self.parent);
932 infer[self.pat_id].clone() 945 let ty = infer[self.pat_id].clone();
946 let def = DefWithBodyId::from(self.parent);
947 let resolver = def.resolver(db);
948 let krate = def.module(db).krate;
949 let environment = TraitEnvironment::lower(db, &resolver);
950 Type { krate, ty: InEnvironment { value: ty, environment } }
933 } 951 }
934 952
935 pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { 953 pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> {
@@ -986,6 +1004,140 @@ impl ImplBlock {
986 } 1004 }
987} 1005}
988 1006
1007#[derive(Clone, PartialEq, Eq)]
1008pub struct Type {
1009 pub(crate) krate: CrateId,
1010 pub(crate) ty: InEnvironment<Ty>,
1011}
1012
1013impl Type {
1014 pub fn is_bool(&self) -> bool {
1015 match &self.ty.value {
1016 Ty::Apply(a_ty) => match a_ty.ctor {
1017 TypeCtor::Bool => true,
1018 _ => false,
1019 },
1020 _ => false,
1021 }
1022 }
1023
1024 pub fn is_mutable_reference(&self) -> bool {
1025 match &self.ty.value {
1026 Ty::Apply(a_ty) => match a_ty.ctor {
1027 TypeCtor::Ref(Mutability::Mut) => true,
1028 _ => false,
1029 },
1030 _ => false,
1031 }
1032 }
1033
1034 pub fn is_unknown(&self) -> bool {
1035 match &self.ty.value {
1036 Ty::Unknown => true,
1037 _ => false,
1038 }
1039 }
1040
1041 // FIXME: this method is broken, as it doesn't take closures into account.
1042 pub fn as_callable(&self) -> Option<CallableDef> {
1043 Some(self.ty.value.as_callable()?.0)
1044 }
1045
1046 pub fn contains_unknown(&self) -> bool {
1047 return go(&self.ty.value);
1048
1049 fn go(ty: &Ty) -> bool {
1050 match ty {
1051 Ty::Unknown => true,
1052 Ty::Apply(a_ty) => a_ty.parameters.iter().any(go),
1053 _ => false,
1054 }
1055 }
1056 }
1057
1058 pub fn fields(&self, db: &impl HirDatabase) -> Vec<(StructField, Type)> {
1059 let mut res = Vec::new();
1060 if let Ty::Apply(a_ty) = &self.ty.value {
1061 match a_ty.ctor {
1062 ty::TypeCtor::Adt(Adt::Struct(s)) => {
1063 for field in s.fields(db) {
1064 let ty = field.ty(db).subst(&a_ty.parameters);
1065 res.push((field, self.derived(ty)));
1066 }
1067 }
1068 _ => {}
1069 }
1070 };
1071 res
1072 }
1073
1074 pub fn tuple_fields(&self, _db: &impl HirDatabase) -> Vec<Type> {
1075 let mut res = Vec::new();
1076 if let Ty::Apply(a_ty) = &self.ty.value {
1077 match a_ty.ctor {
1078 ty::TypeCtor::Tuple { .. } => {
1079 for ty in a_ty.parameters.iter() {
1080 let ty = ty.clone().subst(&a_ty.parameters);
1081 res.push(self.derived(ty));
1082 }
1083 }
1084 _ => {}
1085 }
1086 };
1087 res
1088 }
1089
1090 pub fn variant_fields(
1091 &self,
1092 db: &impl HirDatabase,
1093 def: VariantDef,
1094 ) -> Vec<(StructField, Type)> {
1095 // FIXME: check that ty and def match
1096 match &self.ty.value {
1097 Ty::Apply(a_ty) => def
1098 .fields(db)
1099 .into_iter()
1100 .map(|it| (it, self.derived(it.ty(db).subst(&a_ty.parameters))))
1101 .collect(),
1102 _ => Vec::new(),
1103 }
1104 }
1105
1106 pub fn autoderef<'a>(&'a self, db: &'a impl HirDatabase) -> impl Iterator<Item = Type> + 'a {
1107 // There should be no inference vars in types passed here
1108 // FIXME check that?
1109 let canonical = crate::ty::Canonical { value: self.ty.value.clone(), num_vars: 0 };
1110 let environment = self.ty.environment.clone();
1111 let ty = InEnvironment { value: canonical, environment: environment.clone() };
1112 ty::autoderef(db, Some(self.krate), ty)
1113 .map(|canonical| canonical.value)
1114 .map(move |ty| self.derived(ty))
1115 }
1116
1117 // FIXME: remove
1118 pub fn into_ty(self) -> Ty {
1119 self.ty.value
1120 }
1121
1122 pub fn as_adt(&self) -> Option<Adt> {
1123 let (adt, _subst) = self.ty.value.as_adt()?;
1124 Some(adt)
1125 }
1126
1127 fn derived(&self, ty: Ty) -> Type {
1128 Type {
1129 krate: self.krate,
1130 ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
1131 }
1132 }
1133}
1134
1135impl HirDisplay for Type {
1136 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> std::fmt::Result {
1137 self.ty.value.hir_fmt(f)
1138 }
1139}
1140
989/// For IDE only 1141/// For IDE only
990pub enum ScopeDef { 1142pub enum ScopeDef {
991 ModuleDef(ModuleDef), 1143 ModuleDef(ModuleDef),