diff options
author | Aleksey Kladov <[email protected]> | 2019-11-26 11:02:57 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-11-26 11:02:57 +0000 |
commit | e5eadb339039e21718d382c0b3d02a4bf053b3f4 (patch) | |
tree | 2f7839288ce5676a89c6d6062cbaf70544e0beed /crates/ra_hir | |
parent | 5901cc736074bbc4d780a8e45079d405ab2cec4b (diff) |
Introduce hir::Type
It should provide a convenient API over more low-level Ty
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 166 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 46 |
3 files changed, 185 insertions, 29 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 | }; |
18 | use hir_expand::{ | 18 | use hir_expand::{ |
@@ -26,8 +26,12 @@ use ra_syntax::{ast, AstNode, SyntaxNode}; | |||
26 | use crate::{ | 26 | use 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 { | |||
469 | impl_froms!(Adt: Struct, Union, Enum); | 473 | impl_froms!(Adt: Struct, Union, Enum); |
470 | 474 | ||
471 | impl Adt { | 475 | impl 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 | ||
779 | impl TypeAlias { | 787 | impl 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)] | ||
1008 | pub struct Type { | ||
1009 | pub(crate) krate: CrateId, | ||
1010 | pub(crate) ty: InEnvironment<Ty>, | ||
1011 | } | ||
1012 | |||
1013 | impl 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 | |||
1135 | impl 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 |
990 | pub enum ScopeDef { | 1142 | pub enum ScopeDef { |
991 | ModuleDef(ModuleDef), | 1143 | ModuleDef(ModuleDef), |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 843ce6a88..b88e4c745 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -51,7 +51,7 @@ pub use crate::{ | |||
51 | src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, | 51 | src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, |
52 | DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam, | 52 | DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam, |
53 | HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, | 53 | HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, |
54 | Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, | 54 | Static, Struct, StructField, Trait, Type, TypeAlias, Union, VariantDef, |
55 | }, | 55 | }, |
56 | expr::ExprScopes, | 56 | expr::ExprScopes, |
57 | from_source::FromSource, | 57 | from_source::FromSource, |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index cbfeca3ab..95a94c3f0 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -28,10 +28,10 @@ use crate::{ | |||
28 | expr::{BodySourceMap, ExprScopes, ScopeId}, | 28 | expr::{BodySourceMap, ExprScopes, ScopeId}, |
29 | ty::{ | 29 | ty::{ |
30 | method_resolution::{self, implements_trait}, | 30 | method_resolution::{self, implements_trait}, |
31 | TraitEnvironment, | 31 | InEnvironment, TraitEnvironment, Ty, |
32 | }, | 32 | }, |
33 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, | 33 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, |
34 | GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias, | 34 | GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { | 37 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { |
@@ -198,14 +198,18 @@ impl SourceAnalyzer { | |||
198 | self.body_source_map.as_ref()?.node_pat(src) | 198 | self.body_source_map.as_ref()?.node_pat(src) |
199 | } | 199 | } |
200 | 200 | ||
201 | pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> { | 201 | pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> { |
202 | let expr_id = self.expr_id(expr)?; | 202 | let expr_id = self.expr_id(expr)?; |
203 | Some(self.infer.as_ref()?[expr_id].clone()) | 203 | let ty = self.infer.as_ref()?[expr_id].clone(); |
204 | let environment = TraitEnvironment::lower(db, &self.resolver); | ||
205 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | ||
204 | } | 206 | } |
205 | 207 | ||
206 | pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> { | 208 | pub fn type_of_pat(&self, db: &impl HirDatabase, pat: &ast::Pat) -> Option<Type> { |
207 | let pat_id = self.pat_id(pat)?; | 209 | let pat_id = self.pat_id(pat)?; |
208 | Some(self.infer.as_ref()?[pat_id].clone()) | 210 | let ty = self.infer.as_ref()?[pat_id].clone(); |
211 | let environment = TraitEnvironment::lower(db, &self.resolver); | ||
212 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | ||
209 | } | 213 | } |
210 | 214 | ||
211 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | 215 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { |
@@ -361,14 +365,14 @@ impl SourceAnalyzer { | |||
361 | pub fn iterate_method_candidates<T>( | 365 | pub fn iterate_method_candidates<T>( |
362 | &self, | 366 | &self, |
363 | db: &impl HirDatabase, | 367 | db: &impl HirDatabase, |
364 | ty: Ty, | 368 | ty: &Type, |
365 | name: Option<&Name>, | 369 | name: Option<&Name>, |
366 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, | 370 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
367 | ) -> Option<T> { | 371 | ) -> Option<T> { |
368 | // There should be no inference vars in types passed here | 372 | // There should be no inference vars in types passed here |
369 | // FIXME check that? | 373 | // FIXME check that? |
370 | // FIXME replace Unknown by bound vars here | 374 | // FIXME replace Unknown by bound vars here |
371 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 375 | let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 }; |
372 | method_resolution::iterate_method_candidates( | 376 | method_resolution::iterate_method_candidates( |
373 | &canonical, | 377 | &canonical, |
374 | db, | 378 | db, |
@@ -403,19 +407,19 @@ impl SourceAnalyzer { | |||
403 | ) | 407 | ) |
404 | } | 408 | } |
405 | 409 | ||
406 | pub fn autoderef<'a>( | 410 | // pub fn autoderef<'a>( |
407 | &'a self, | 411 | // &'a self, |
408 | db: &'a impl HirDatabase, | 412 | // db: &'a impl HirDatabase, |
409 | ty: Ty, | 413 | // ty: Ty, |
410 | ) -> impl Iterator<Item = Ty> + 'a { | 414 | // ) -> impl Iterator<Item = Ty> + 'a { |
411 | // There should be no inference vars in types passed here | 415 | // // There should be no inference vars in types passed here |
412 | // FIXME check that? | 416 | // // FIXME check that? |
413 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 417 | // let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; |
414 | let krate = self.resolver.krate(); | 418 | // let krate = self.resolver.krate(); |
415 | let environment = TraitEnvironment::lower(db, &self.resolver); | 419 | // let environment = TraitEnvironment::lower(db, &self.resolver); |
416 | let ty = crate::ty::InEnvironment { value: canonical, environment }; | 420 | // let ty = crate::ty::InEnvironment { value: canonical, environment }; |
417 | crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value) | 421 | // crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value) |
418 | } | 422 | // } |
419 | 423 | ||
420 | /// Checks that particular type `ty` implements `std::future::Future`. | 424 | /// Checks that particular type `ty` implements `std::future::Future`. |
421 | /// This function is used in `.await` syntax completion. | 425 | /// This function is used in `.await` syntax completion. |