aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r--crates/ra_hir/src/code_model.rs211
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};
18use hir_expand::{ 18use hir_expand::{
19 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
@@ -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
@@ -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 {
469impl_froms!(Adt: Struct, Union, Enum); 495impl_froms!(Adt: Struct, Union, Enum);
470 496
471impl Adt { 497impl 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)]
494pub enum VariantDef { 524pub enum VariantDef {
495 Struct(Struct), 525 Struct(Struct),
526 Union(Union),
496 EnumVariant(EnumVariant), 527 EnumVariant(EnumVariant),
497} 528}
498impl_froms!(VariantDef: Struct, EnumVariant); 529impl_froms!(VariantDef: Struct, Union, EnumVariant);
499 530
500impl VariantDef { 531impl 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
779impl TypeAlias { 814impl 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
954impl ImplBlock { 999impl 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)]
1044pub struct Type {
1045 pub(crate) krate: CrateId,
1046 pub(crate) ty: InEnvironment<Ty>,
1047}
1048
1049impl 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
1176impl 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
990pub enum ScopeDef { 1183pub enum ScopeDef {
991 ModuleDef(ModuleDef), 1184 ModuleDef(ModuleDef),