diff options
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 211 |
1 files changed, 202 insertions, 9 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index f7fc80d4e..821f919d4 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -10,10 +10,10 @@ 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 | AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId, |
15 | LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, | 15 | HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, |
16 | StaticId, StructId, TraitId, TypeAliasId, UnionId, | 16 | Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId, |
17 | }; | 17 | }; |
18 | use hir_expand::{ | 18 | use hir_expand::{ |
19 | diagnostics::DiagnosticSink, | 19 | diagnostics::DiagnosticSink, |
@@ -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 |
@@ -379,6 +383,28 @@ impl Union { | |||
379 | pub fn ty(self, db: &impl HirDatabase) -> Ty { | 383 | pub fn ty(self, db: &impl HirDatabase) -> Ty { |
380 | db.type_for_def(self.into(), Namespace::Types) | 384 | db.type_for_def(self.into(), Namespace::Types) |
381 | } | 385 | } |
386 | |||
387 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { | ||
388 | db.union_data(self.id) | ||
389 | .variant_data | ||
390 | .fields() | ||
391 | .iter() | ||
392 | .map(|(id, _)| StructField { parent: self.into(), id }) | ||
393 | .collect() | ||
394 | } | ||
395 | |||
396 | pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | ||
397 | db.union_data(self.id) | ||
398 | .variant_data | ||
399 | .fields() | ||
400 | .iter() | ||
401 | .find(|(_id, data)| data.name == *name) | ||
402 | .map(|(id, _)| StructField { parent: self.into(), id }) | ||
403 | } | ||
404 | |||
405 | fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { | ||
406 | db.union_data(self.id).variant_data.clone() | ||
407 | } | ||
382 | } | 408 | } |
383 | 409 | ||
384 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 410 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -469,6 +495,10 @@ pub enum Adt { | |||
469 | impl_froms!(Adt: Struct, Union, Enum); | 495 | impl_froms!(Adt: Struct, Union, Enum); |
470 | 496 | ||
471 | impl Adt { | 497 | impl Adt { |
498 | pub fn has_non_default_type_params(self, db: &impl HirDatabase) -> bool { | ||
499 | let subst = db.generic_defaults(self.into()); | ||
500 | subst.iter().any(|ty| ty == &Ty::Unknown) | ||
501 | } | ||
472 | pub fn ty(self, db: &impl HirDatabase) -> Ty { | 502 | pub fn ty(self, db: &impl HirDatabase) -> Ty { |
473 | match self { | 503 | match self { |
474 | Adt::Struct(it) => it.ty(db), | 504 | Adt::Struct(it) => it.ty(db), |
@@ -493,14 +523,16 @@ impl Adt { | |||
493 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 523 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
494 | pub enum VariantDef { | 524 | pub enum VariantDef { |
495 | Struct(Struct), | 525 | Struct(Struct), |
526 | Union(Union), | ||
496 | EnumVariant(EnumVariant), | 527 | EnumVariant(EnumVariant), |
497 | } | 528 | } |
498 | impl_froms!(VariantDef: Struct, EnumVariant); | 529 | impl_froms!(VariantDef: Struct, Union, EnumVariant); |
499 | 530 | ||
500 | impl VariantDef { | 531 | impl VariantDef { |
501 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { | 532 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { |
502 | match self { | 533 | match self { |
503 | VariantDef::Struct(it) => it.fields(db), | 534 | VariantDef::Struct(it) => it.fields(db), |
535 | VariantDef::Union(it) => it.fields(db), | ||
504 | VariantDef::EnumVariant(it) => it.fields(db), | 536 | VariantDef::EnumVariant(it) => it.fields(db), |
505 | } | 537 | } |
506 | } | 538 | } |
@@ -508,6 +540,7 @@ impl VariantDef { | |||
508 | pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | 540 | pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { |
509 | match self { | 541 | match self { |
510 | VariantDef::Struct(it) => it.field(db, name), | 542 | VariantDef::Struct(it) => it.field(db, name), |
543 | VariantDef::Union(it) => it.field(db, name), | ||
511 | VariantDef::EnumVariant(it) => it.field(db, name), | 544 | VariantDef::EnumVariant(it) => it.field(db, name), |
512 | } | 545 | } |
513 | } | 546 | } |
@@ -515,6 +548,7 @@ impl VariantDef { | |||
515 | pub fn module(self, db: &impl HirDatabase) -> Module { | 548 | pub fn module(self, db: &impl HirDatabase) -> Module { |
516 | match self { | 549 | match self { |
517 | VariantDef::Struct(it) => it.module(db), | 550 | VariantDef::Struct(it) => it.module(db), |
551 | VariantDef::Union(it) => it.module(db), | ||
518 | VariantDef::EnumVariant(it) => it.module(db), | 552 | VariantDef::EnumVariant(it) => it.module(db), |
519 | } | 553 | } |
520 | } | 554 | } |
@@ -522,6 +556,7 @@ impl VariantDef { | |||
522 | pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { | 556 | pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { |
523 | match self { | 557 | match self { |
524 | VariantDef::Struct(it) => it.variant_data(db), | 558 | VariantDef::Struct(it) => it.variant_data(db), |
559 | VariantDef::Union(it) => it.variant_data(db), | ||
525 | VariantDef::EnumVariant(it) => it.variant_data(db), | 560 | VariantDef::EnumVariant(it) => it.variant_data(db), |
526 | } | 561 | } |
527 | } | 562 | } |
@@ -777,6 +812,11 @@ pub struct TypeAlias { | |||
777 | } | 812 | } |
778 | 813 | ||
779 | impl TypeAlias { | 814 | impl TypeAlias { |
815 | pub fn has_non_default_type_params(self, db: &impl HirDatabase) -> bool { | ||
816 | let subst = db.generic_defaults(self.id.into()); | ||
817 | subst.iter().any(|ty| ty == &Ty::Unknown) | ||
818 | } | ||
819 | |||
780 | pub fn module(self, db: &impl DefDatabase) -> Module { | 820 | pub fn module(self, db: &impl DefDatabase) -> Module { |
781 | Module { id: self.id.lookup(db).module(db) } | 821 | Module { id: self.id.lookup(db).module(db) } |
782 | } | 822 | } |
@@ -927,9 +967,14 @@ impl Local { | |||
927 | self.parent.module(db) | 967 | self.parent.module(db) |
928 | } | 968 | } |
929 | 969 | ||
930 | pub fn ty(self, db: &impl HirDatabase) -> Ty { | 970 | pub fn ty(self, db: &impl HirDatabase) -> Type { |
931 | let infer = db.infer(self.parent); | 971 | let infer = db.infer(self.parent); |
932 | infer[self.pat_id].clone() | 972 | let ty = infer[self.pat_id].clone(); |
973 | let def = DefWithBodyId::from(self.parent); | ||
974 | let resolver = def.resolver(db); | ||
975 | let krate = def.module(db).krate; | ||
976 | let environment = TraitEnvironment::lower(db, &resolver); | ||
977 | Type { krate, ty: InEnvironment { value: ty, environment } } | ||
933 | } | 978 | } |
934 | 979 | ||
935 | pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { | 980 | pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { |
@@ -952,6 +997,15 @@ pub struct ImplBlock { | |||
952 | } | 997 | } |
953 | 998 | ||
954 | impl ImplBlock { | 999 | impl ImplBlock { |
1000 | pub fn all_in_crate(db: &impl HirDatabase, krate: Crate) -> Vec<ImplBlock> { | ||
1001 | let impls = db.impls_in_crate(krate.crate_id); | ||
1002 | impls.all_impls().map(Self::from).collect() | ||
1003 | } | ||
1004 | pub fn for_trait(db: &impl HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplBlock> { | ||
1005 | let impls = db.impls_in_crate(krate.crate_id); | ||
1006 | impls.lookup_impl_blocks_for_trait(trait_).map(Self::from).collect() | ||
1007 | } | ||
1008 | |||
955 | pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { | 1009 | pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { |
956 | db.impl_data(self.id).target_trait.clone() | 1010 | db.impl_data(self.id).target_trait.clone() |
957 | } | 1011 | } |
@@ -986,6 +1040,145 @@ impl ImplBlock { | |||
986 | } | 1040 | } |
987 | } | 1041 | } |
988 | 1042 | ||
1043 | #[derive(Clone, PartialEq, Eq)] | ||
1044 | pub struct Type { | ||
1045 | pub(crate) krate: CrateId, | ||
1046 | pub(crate) ty: InEnvironment<Ty>, | ||
1047 | } | ||
1048 | |||
1049 | impl Type { | ||
1050 | pub fn is_bool(&self) -> bool { | ||
1051 | match &self.ty.value { | ||
1052 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
1053 | TypeCtor::Bool => true, | ||
1054 | _ => false, | ||
1055 | }, | ||
1056 | _ => false, | ||
1057 | } | ||
1058 | } | ||
1059 | |||
1060 | pub fn is_mutable_reference(&self) -> bool { | ||
1061 | match &self.ty.value { | ||
1062 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
1063 | TypeCtor::Ref(Mutability::Mut) => true, | ||
1064 | _ => false, | ||
1065 | }, | ||
1066 | _ => false, | ||
1067 | } | ||
1068 | } | ||
1069 | |||
1070 | pub fn is_unknown(&self) -> bool { | ||
1071 | match &self.ty.value { | ||
1072 | Ty::Unknown => true, | ||
1073 | _ => false, | ||
1074 | } | ||
1075 | } | ||
1076 | |||
1077 | // FIXME: this method is broken, as it doesn't take closures into account. | ||
1078 | pub fn as_callable(&self) -> Option<CallableDef> { | ||
1079 | Some(self.ty.value.as_callable()?.0) | ||
1080 | } | ||
1081 | |||
1082 | pub fn contains_unknown(&self) -> bool { | ||
1083 | return go(&self.ty.value); | ||
1084 | |||
1085 | fn go(ty: &Ty) -> bool { | ||
1086 | match ty { | ||
1087 | Ty::Unknown => true, | ||
1088 | Ty::Apply(a_ty) => a_ty.parameters.iter().any(go), | ||
1089 | _ => false, | ||
1090 | } | ||
1091 | } | ||
1092 | } | ||
1093 | |||
1094 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<(StructField, Type)> { | ||
1095 | if let Ty::Apply(a_ty) = &self.ty.value { | ||
1096 | match a_ty.ctor { | ||
1097 | ty::TypeCtor::Adt(AdtId::StructId(s)) => { | ||
1098 | let var_def = s.into(); | ||
1099 | return db | ||
1100 | .field_types(var_def) | ||
1101 | .iter() | ||
1102 | .map(|(local_id, ty)| { | ||
1103 | let def = StructField { parent: var_def.into(), id: local_id }; | ||
1104 | let ty = ty.clone().subst(&a_ty.parameters); | ||
1105 | (def, self.derived(ty)) | ||
1106 | }) | ||
1107 | .collect(); | ||
1108 | } | ||
1109 | _ => {} | ||
1110 | } | ||
1111 | }; | ||
1112 | Vec::new() | ||
1113 | } | ||
1114 | |||
1115 | pub fn tuple_fields(&self, _db: &impl HirDatabase) -> Vec<Type> { | ||
1116 | let mut res = Vec::new(); | ||
1117 | if let Ty::Apply(a_ty) = &self.ty.value { | ||
1118 | match a_ty.ctor { | ||
1119 | ty::TypeCtor::Tuple { .. } => { | ||
1120 | for ty in a_ty.parameters.iter() { | ||
1121 | let ty = ty.clone().subst(&a_ty.parameters); | ||
1122 | res.push(self.derived(ty)); | ||
1123 | } | ||
1124 | } | ||
1125 | _ => {} | ||
1126 | } | ||
1127 | }; | ||
1128 | res | ||
1129 | } | ||
1130 | |||
1131 | pub fn variant_fields( | ||
1132 | &self, | ||
1133 | db: &impl HirDatabase, | ||
1134 | def: VariantDef, | ||
1135 | ) -> Vec<(StructField, Type)> { | ||
1136 | // FIXME: check that ty and def match | ||
1137 | match &self.ty.value { | ||
1138 | Ty::Apply(a_ty) => def | ||
1139 | .fields(db) | ||
1140 | .into_iter() | ||
1141 | .map(|it| (it, self.derived(it.ty(db).subst(&a_ty.parameters)))) | ||
1142 | .collect(), | ||
1143 | _ => Vec::new(), | ||
1144 | } | ||
1145 | } | ||
1146 | |||
1147 | pub fn autoderef<'a>(&'a self, db: &'a impl HirDatabase) -> impl Iterator<Item = Type> + 'a { | ||
1148 | // There should be no inference vars in types passed here | ||
1149 | // FIXME check that? | ||
1150 | let canonical = crate::ty::Canonical { value: self.ty.value.clone(), num_vars: 0 }; | ||
1151 | let environment = self.ty.environment.clone(); | ||
1152 | let ty = InEnvironment { value: canonical, environment: environment.clone() }; | ||
1153 | ty::autoderef(db, Some(self.krate), ty) | ||
1154 | .map(|canonical| canonical.value) | ||
1155 | .map(move |ty| self.derived(ty)) | ||
1156 | } | ||
1157 | |||
1158 | // FIXME: remove | ||
1159 | pub fn into_ty(self) -> Ty { | ||
1160 | self.ty.value | ||
1161 | } | ||
1162 | |||
1163 | pub fn as_adt(&self) -> Option<Adt> { | ||
1164 | let (adt, _subst) = self.ty.value.as_adt()?; | ||
1165 | Some(adt) | ||
1166 | } | ||
1167 | |||
1168 | fn derived(&self, ty: Ty) -> Type { | ||
1169 | Type { | ||
1170 | krate: self.krate, | ||
1171 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, | ||
1172 | } | ||
1173 | } | ||
1174 | } | ||
1175 | |||
1176 | impl HirDisplay for Type { | ||
1177 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> std::fmt::Result { | ||
1178 | self.ty.value.hir_fmt(f) | ||
1179 | } | ||
1180 | } | ||
1181 | |||
989 | /// For IDE only | 1182 | /// For IDE only |
990 | pub enum ScopeDef { | 1183 | pub enum ScopeDef { |
991 | ModuleDef(ModuleDef), | 1184 | ModuleDef(ModuleDef), |