diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 231 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/diagnostics.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/has_source.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 329 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics/source_to_def.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 60 |
9 files changed, 527 insertions, 160 deletions
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index ba7b39a19..c260bb193 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml | |||
@@ -3,6 +3,7 @@ edition = "2018" | |||
3 | name = "ra_hir" | 3 | name = "ra_hir" |
4 | version = "0.1.0" | 4 | version = "0.1.0" |
5 | authors = ["rust-analyzer developers"] | 5 | authors = ["rust-analyzer developers"] |
6 | license = "MIT OR Apache-2.0" | ||
6 | 7 | ||
7 | [lib] | 8 | [lib] |
8 | doctest = false | 9 | doctest = false |
@@ -15,6 +16,7 @@ arrayvec = "0.5.1" | |||
15 | 16 | ||
16 | itertools = "0.9.0" | 17 | itertools = "0.9.0" |
17 | 18 | ||
19 | stdx = { path = "../stdx" } | ||
18 | ra_syntax = { path = "../ra_syntax" } | 20 | ra_syntax = { path = "../ra_syntax" } |
19 | ra_db = { path = "../ra_db" } | 21 | ra_db = { path = "../ra_db" } |
20 | ra_prof = { path = "../ra_prof" } | 22 | ra_prof = { path = "../ra_prof" } |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index e40aeffbc..9891b0785 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -9,6 +9,7 @@ use hir_def::{ | |||
9 | builtin_type::BuiltinType, | 9 | builtin_type::BuiltinType, |
10 | docs::Documentation, | 10 | docs::Documentation, |
11 | expr::{BindingAnnotation, Pat, PatId}, | 11 | expr::{BindingAnnotation, Pat, PatId}, |
12 | import_map, | ||
12 | per_ns::PerNs, | 13 | per_ns::PerNs, |
13 | resolver::{HasResolver, Resolver}, | 14 | resolver::{HasResolver, Resolver}, |
14 | type_ref::{Mutability, TypeRef}, | 15 | type_ref::{Mutability, TypeRef}, |
@@ -24,22 +25,22 @@ use hir_expand::{ | |||
24 | use hir_ty::{ | 25 | use hir_ty::{ |
25 | autoderef, | 26 | autoderef, |
26 | display::{HirDisplayError, HirFormatter}, | 27 | display::{HirDisplayError, HirFormatter}, |
27 | expr::ExprValidator, | 28 | method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, |
28 | method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty, | 29 | TraitEnvironment, Ty, TyDefId, TypeCtor, |
29 | TyDefId, TypeCtor, | ||
30 | }; | 30 | }; |
31 | use ra_db::{CrateId, CrateName, Edition, FileId}; | 31 | use ra_db::{CrateId, Edition, FileId}; |
32 | use ra_prof::profile; | 32 | use ra_prof::profile; |
33 | use ra_syntax::{ | 33 | use ra_syntax::{ |
34 | ast::{self, AttrsOwner, NameOwner}, | 34 | ast::{self, AttrsOwner, NameOwner}, |
35 | AstNode, | 35 | AstNode, |
36 | }; | 36 | }; |
37 | use rustc_hash::FxHashSet; | 37 | use rustc_hash::FxHashSet; |
38 | use stdx::impl_from; | ||
38 | 39 | ||
39 | use crate::{ | 40 | use crate::{ |
40 | db::{DefDatabase, HirDatabase}, | 41 | db::{DefDatabase, HirDatabase}, |
41 | has_source::HasSource, | 42 | has_source::HasSource, |
42 | CallableDef, HirDisplay, InFile, Name, | 43 | CallableDefId, HirDisplay, InFile, Name, |
43 | }; | 44 | }; |
44 | 45 | ||
45 | /// hir::Crate describes a single crate. It's the main interface with which | 46 | /// hir::Crate describes a single crate. It's the main interface with which |
@@ -94,8 +95,25 @@ impl Crate { | |||
94 | db.crate_graph()[self.id].edition | 95 | db.crate_graph()[self.id].edition |
95 | } | 96 | } |
96 | 97 | ||
97 | pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateName> { | 98 | pub fn display_name(self, db: &dyn HirDatabase) -> Option<String> { |
98 | db.crate_graph()[self.id].display_name.as_ref().cloned() | 99 | db.crate_graph()[self.id].display_name.clone() |
100 | } | ||
101 | |||
102 | pub fn query_external_importables( | ||
103 | self, | ||
104 | db: &dyn DefDatabase, | ||
105 | query: &str, | ||
106 | ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { | ||
107 | import_map::search_dependencies( | ||
108 | db, | ||
109 | self.into(), | ||
110 | import_map::Query::new(query).anchor_end().case_sensitive().limit(40), | ||
111 | ) | ||
112 | .into_iter() | ||
113 | .map(|item| match item { | ||
114 | ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()), | ||
115 | ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()), | ||
116 | }) | ||
99 | } | 117 | } |
100 | 118 | ||
101 | pub fn all(db: &dyn HirDatabase) -> Vec<Crate> { | 119 | pub fn all(db: &dyn HirDatabase) -> Vec<Crate> { |
@@ -122,8 +140,8 @@ pub enum ModuleDef { | |||
122 | TypeAlias(TypeAlias), | 140 | TypeAlias(TypeAlias), |
123 | BuiltinType(BuiltinType), | 141 | BuiltinType(BuiltinType), |
124 | } | 142 | } |
125 | impl_froms!( | 143 | impl_from!( |
126 | ModuleDef: Module, | 144 | Module, |
127 | Function, | 145 | Function, |
128 | Adt(Struct, Enum, Union), | 146 | Adt(Struct, Enum, Union), |
129 | EnumVariant, | 147 | EnumVariant, |
@@ -132,6 +150,7 @@ impl_froms!( | |||
132 | Trait, | 150 | Trait, |
133 | TypeAlias, | 151 | TypeAlias, |
134 | BuiltinType | 152 | BuiltinType |
153 | for ModuleDef | ||
135 | ); | 154 | ); |
136 | 155 | ||
137 | impl ModuleDef { | 156 | impl ModuleDef { |
@@ -168,10 +187,27 @@ impl ModuleDef { | |||
168 | 187 | ||
169 | module.visibility_of(db, self) | 188 | module.visibility_of(db, self) |
170 | } | 189 | } |
190 | |||
191 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | ||
192 | match self { | ||
193 | ModuleDef::Adt(it) => Some(it.name(db)), | ||
194 | ModuleDef::Trait(it) => Some(it.name(db)), | ||
195 | ModuleDef::Function(it) => Some(it.name(db)), | ||
196 | ModuleDef::EnumVariant(it) => Some(it.name(db)), | ||
197 | ModuleDef::TypeAlias(it) => Some(it.name(db)), | ||
198 | |||
199 | ModuleDef::Module(it) => it.name(db), | ||
200 | ModuleDef::Const(it) => it.name(db), | ||
201 | ModuleDef::Static(it) => it.name(db), | ||
202 | |||
203 | ModuleDef::BuiltinType(it) => Some(it.as_name()), | ||
204 | } | ||
205 | } | ||
171 | } | 206 | } |
172 | 207 | ||
173 | pub use hir_def::{ | 208 | pub use hir_def::{ |
174 | attr::Attrs, item_scope::ItemInNs, visibility::Visibility, AssocItemId, AssocItemLoc, | 209 | attr::Attrs, item_scope::ItemInNs, item_tree::ItemTreeNode, visibility::Visibility, |
210 | AssocItemId, AssocItemLoc, | ||
175 | }; | 211 | }; |
176 | 212 | ||
177 | impl Module { | 213 | impl Module { |
@@ -504,12 +540,12 @@ pub enum Adt { | |||
504 | Union(Union), | 540 | Union(Union), |
505 | Enum(Enum), | 541 | Enum(Enum), |
506 | } | 542 | } |
507 | impl_froms!(Adt: Struct, Union, Enum); | 543 | impl_from!(Struct, Union, Enum for Adt); |
508 | 544 | ||
509 | impl Adt { | 545 | impl Adt { |
510 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { | 546 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { |
511 | let subst = db.generic_defaults(self.into()); | 547 | let subst = db.generic_defaults(self.into()); |
512 | subst.iter().any(|ty| ty == &Ty::Unknown) | 548 | subst.iter().any(|ty| &ty.value == &Ty::Unknown) |
513 | } | 549 | } |
514 | 550 | ||
515 | /// Turns this ADT into a type. Any type parameters of the ADT will be | 551 | /// Turns this ADT into a type. Any type parameters of the ADT will be |
@@ -547,7 +583,7 @@ pub enum VariantDef { | |||
547 | Union(Union), | 583 | Union(Union), |
548 | EnumVariant(EnumVariant), | 584 | EnumVariant(EnumVariant), |
549 | } | 585 | } |
550 | impl_froms!(VariantDef: Struct, Union, EnumVariant); | 586 | impl_from!(Struct, Union, EnumVariant for VariantDef); |
551 | 587 | ||
552 | impl VariantDef { | 588 | impl VariantDef { |
553 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { | 589 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { |
@@ -590,8 +626,7 @@ pub enum DefWithBody { | |||
590 | Static(Static), | 626 | Static(Static), |
591 | Const(Const), | 627 | Const(Const), |
592 | } | 628 | } |
593 | 629 | impl_from!(Function, Const, Static for DefWithBody); | |
594 | impl_froms!(DefWithBody: Function, Const, Static); | ||
595 | 630 | ||
596 | impl DefWithBody { | 631 | impl DefWithBody { |
597 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 632 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
@@ -637,12 +672,12 @@ impl Function { | |||
637 | db.function_data(self.id).params.clone() | 672 | db.function_data(self.id).params.clone() |
638 | } | 673 | } |
639 | 674 | ||
675 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { | ||
676 | db.function_data(self.id).is_unsafe | ||
677 | } | ||
678 | |||
640 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 679 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { |
641 | let _p = profile("Function::diagnostics"); | 680 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink) |
642 | let infer = db.infer(self.id.into()); | ||
643 | infer.add_diagnostics(db, self.id, sink); | ||
644 | let mut validator = ExprValidator::new(self.id, infer, sink); | ||
645 | validator.validate_body(db); | ||
646 | } | 681 | } |
647 | } | 682 | } |
648 | 683 | ||
@@ -735,7 +770,7 @@ pub struct TypeAlias { | |||
735 | impl TypeAlias { | 770 | impl TypeAlias { |
736 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { | 771 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { |
737 | let subst = db.generic_defaults(self.id.into()); | 772 | let subst = db.generic_defaults(self.id.into()); |
738 | subst.iter().any(|ty| ty == &Ty::Unknown) | 773 | subst.iter().any(|ty| &ty.value == &Ty::Unknown) |
739 | } | 774 | } |
740 | 775 | ||
741 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 776 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
@@ -834,7 +869,7 @@ where | |||
834 | ID: Lookup<Data = AssocItemLoc<AST>>, | 869 | ID: Lookup<Data = AssocItemLoc<AST>>, |
835 | DEF: From<ID>, | 870 | DEF: From<ID>, |
836 | CTOR: FnOnce(DEF) -> AssocItem, | 871 | CTOR: FnOnce(DEF) -> AssocItem, |
837 | AST: AstNode, | 872 | AST: ItemTreeNode, |
838 | { | 873 | { |
839 | match id.lookup(db.upcast()).container { | 874 | match id.lookup(db.upcast()).container { |
840 | AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))), | 875 | AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))), |
@@ -887,14 +922,15 @@ pub enum GenericDef { | |||
887 | // consts can have type parameters from their parents (i.e. associated consts of traits) | 922 | // consts can have type parameters from their parents (i.e. associated consts of traits) |
888 | Const(Const), | 923 | Const(Const), |
889 | } | 924 | } |
890 | impl_froms!( | 925 | impl_from!( |
891 | GenericDef: Function, | 926 | Function, |
892 | Adt(Struct, Enum, Union), | 927 | Adt(Struct, Enum, Union), |
893 | Trait, | 928 | Trait, |
894 | TypeAlias, | 929 | TypeAlias, |
895 | ImplDef, | 930 | ImplDef, |
896 | EnumVariant, | 931 | EnumVariant, |
897 | Const | 932 | Const |
933 | for GenericDef | ||
898 | ); | 934 | ); |
899 | 935 | ||
900 | impl GenericDef { | 936 | impl GenericDef { |
@@ -915,6 +951,16 @@ pub struct Local { | |||
915 | } | 951 | } |
916 | 952 | ||
917 | impl Local { | 953 | impl Local { |
954 | pub fn is_param(self, db: &dyn HirDatabase) -> bool { | ||
955 | let src = self.source(db); | ||
956 | match src.value { | ||
957 | Either::Left(bind_pat) => { | ||
958 | bind_pat.syntax().ancestors().any(|it| ast::Param::can_cast(it.kind())) | ||
959 | } | ||
960 | Either::Right(_self_param) => true, | ||
961 | } | ||
962 | } | ||
963 | |||
918 | // FIXME: why is this an option? It shouldn't be? | 964 | // FIXME: why is this an option? It shouldn't be? |
919 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 965 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
920 | let body = db.body(self.parent.into()); | 966 | let body = db.body(self.parent.into()); |
@@ -995,7 +1041,10 @@ impl TypeParam { | |||
995 | let local_idx = hir_ty::param_idx(db, self.id)?; | 1041 | let local_idx = hir_ty::param_idx(db, self.id)?; |
996 | let resolver = self.id.parent.resolver(db.upcast()); | 1042 | let resolver = self.id.parent.resolver(db.upcast()); |
997 | let environment = TraitEnvironment::lower(db, &resolver); | 1043 | let environment = TraitEnvironment::lower(db, &resolver); |
998 | params.get(local_idx).cloned().map(|ty| Type { | 1044 | let ty = params.get(local_idx)?.clone(); |
1045 | let subst = Substs::type_params(db, self.id.parent); | ||
1046 | let ty = ty.subst(&subst.prefix(local_idx)); | ||
1047 | Some(Type { | ||
999 | krate: self.id.parent.module(db.upcast()).krate, | 1048 | krate: self.id.parent.module(db.upcast()).krate, |
1000 | ty: InEnvironment { value: ty, environment }, | 1049 | ty: InEnvironment { value: ty, environment }, |
1001 | }) | 1050 | }) |
@@ -1010,12 +1059,14 @@ pub struct ImplDef { | |||
1010 | 1059 | ||
1011 | impl ImplDef { | 1060 | impl ImplDef { |
1012 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> { | 1061 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> { |
1013 | let impls = db.impls_in_crate(krate.id); | 1062 | let inherent = db.inherent_impls_in_crate(krate.id); |
1014 | impls.all_impls().map(Self::from).collect() | 1063 | let trait_ = db.trait_impls_in_crate(krate.id); |
1064 | |||
1065 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() | ||
1015 | } | 1066 | } |
1016 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> { | 1067 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> { |
1017 | let impls = db.impls_in_crate(krate.id); | 1068 | let impls = db.trait_impls_in_crate(krate.id); |
1018 | impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect() | 1069 | impls.for_trait(trait_.id).map(Self::from).collect() |
1019 | } | 1070 | } |
1020 | 1071 | ||
1021 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1072 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
@@ -1144,7 +1195,7 @@ impl Type { | |||
1144 | None => return false, | 1195 | None => return false, |
1145 | }; | 1196 | }; |
1146 | 1197 | ||
1147 | let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1198 | let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1148 | method_resolution::implements_trait( | 1199 | method_resolution::implements_trait( |
1149 | &canonical_ty, | 1200 | &canonical_ty, |
1150 | db, | 1201 | db, |
@@ -1168,14 +1219,14 @@ impl Type { | |||
1168 | self.ty.environment.clone(), | 1219 | self.ty.environment.clone(), |
1169 | hir_ty::Obligation::Trait(trait_ref), | 1220 | hir_ty::Obligation::Trait(trait_ref), |
1170 | ), | 1221 | ), |
1171 | num_vars: 0, | 1222 | kinds: Arc::new([]), |
1172 | }; | 1223 | }; |
1173 | 1224 | ||
1174 | db.trait_solve(self.krate, goal).is_some() | 1225 | db.trait_solve(self.krate, goal).is_some() |
1175 | } | 1226 | } |
1176 | 1227 | ||
1177 | // FIXME: this method is broken, as it doesn't take closures into account. | 1228 | // FIXME: this method is broken, as it doesn't take closures into account. |
1178 | pub fn as_callable(&self) -> Option<CallableDef> { | 1229 | pub fn as_callable(&self) -> Option<CallableDefId> { |
1179 | Some(self.ty.value.as_callable()?.0) | 1230 | Some(self.ty.value.as_callable()?.0) |
1180 | } | 1231 | } |
1181 | 1232 | ||
@@ -1190,6 +1241,10 @@ impl Type { | |||
1190 | ) | 1241 | ) |
1191 | } | 1242 | } |
1192 | 1243 | ||
1244 | pub fn is_raw_ptr(&self) -> bool { | ||
1245 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) | ||
1246 | } | ||
1247 | |||
1193 | pub fn contains_unknown(&self) -> bool { | 1248 | pub fn contains_unknown(&self) -> bool { |
1194 | return go(&self.ty.value); | 1249 | return go(&self.ty.value); |
1195 | 1250 | ||
@@ -1239,7 +1294,7 @@ impl Type { | |||
1239 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { | 1294 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { |
1240 | // There should be no inference vars in types passed here | 1295 | // There should be no inference vars in types passed here |
1241 | // FIXME check that? | 1296 | // FIXME check that? |
1242 | let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1297 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1243 | let environment = self.ty.environment.clone(); | 1298 | let environment = self.ty.environment.clone(); |
1244 | let ty = InEnvironment { value: canonical, environment }; | 1299 | let ty = InEnvironment { value: canonical, environment }; |
1245 | autoderef(db, Some(self.krate), ty) | 1300 | autoderef(db, Some(self.krate), ty) |
@@ -1256,10 +1311,10 @@ impl Type { | |||
1256 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 1311 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
1257 | ) -> Option<T> { | 1312 | ) -> Option<T> { |
1258 | for krate in self.ty.value.def_crates(db, krate.id)? { | 1313 | for krate in self.ty.value.def_crates(db, krate.id)? { |
1259 | let impls = db.impls_in_crate(krate); | 1314 | let impls = db.inherent_impls_in_crate(krate); |
1260 | 1315 | ||
1261 | for impl_def in impls.lookup_impl_defs(&self.ty.value) { | 1316 | for impl_def in impls.for_self_ty(&self.ty.value) { |
1262 | for &item in db.impl_data(impl_def).items.iter() { | 1317 | for &item in db.impl_data(*impl_def).items.iter() { |
1263 | if let Some(result) = callback(item.into()) { | 1318 | if let Some(result) = callback(item.into()) { |
1264 | return Some(result); | 1319 | return Some(result); |
1265 | } | 1320 | } |
@@ -1280,7 +1335,7 @@ impl Type { | |||
1280 | // There should be no inference vars in types passed here | 1335 | // There should be no inference vars in types passed here |
1281 | // FIXME check that? | 1336 | // FIXME check that? |
1282 | // FIXME replace Unknown by bound vars here | 1337 | // FIXME replace Unknown by bound vars here |
1283 | let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1338 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1284 | 1339 | ||
1285 | let env = self.ty.environment.clone(); | 1340 | let env = self.ty.environment.clone(); |
1286 | let krate = krate.id; | 1341 | let krate = krate.id; |
@@ -1311,7 +1366,7 @@ impl Type { | |||
1311 | // There should be no inference vars in types passed here | 1366 | // There should be no inference vars in types passed here |
1312 | // FIXME check that? | 1367 | // FIXME check that? |
1313 | // FIXME replace Unknown by bound vars here | 1368 | // FIXME replace Unknown by bound vars here |
1314 | let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1369 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1315 | 1370 | ||
1316 | let env = self.ty.environment.clone(); | 1371 | let env = self.ty.environment.clone(); |
1317 | let krate = krate.id; | 1372 | let krate = krate.id; |
@@ -1333,6 +1388,27 @@ impl Type { | |||
1333 | Some(adt.into()) | 1388 | Some(adt.into()) |
1334 | } | 1389 | } |
1335 | 1390 | ||
1391 | pub fn as_dyn_trait(&self) -> Option<Trait> { | ||
1392 | self.ty.value.dyn_trait().map(Into::into) | ||
1393 | } | ||
1394 | |||
1395 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { | ||
1396 | self.ty.value.impl_trait_bounds(db).map(|it| { | ||
1397 | it.into_iter() | ||
1398 | .filter_map(|pred| match pred { | ||
1399 | hir_ty::GenericPredicate::Implemented(trait_ref) => { | ||
1400 | Some(Trait::from(trait_ref.trait_)) | ||
1401 | } | ||
1402 | _ => None, | ||
1403 | }) | ||
1404 | .collect() | ||
1405 | }) | ||
1406 | } | ||
1407 | |||
1408 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { | ||
1409 | self.ty.value.associated_type_parent_trait(db).map(Into::into) | ||
1410 | } | ||
1411 | |||
1336 | // FIXME: provide required accessors such that it becomes implementable from outside. | 1412 | // FIXME: provide required accessors such that it becomes implementable from outside. |
1337 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { | 1413 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { |
1338 | match (&self.ty.value, &other.ty.value) { | 1414 | match (&self.ty.value, &other.ty.value) { |
@@ -1354,6 +1430,80 @@ impl Type { | |||
1354 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, | 1430 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, |
1355 | } | 1431 | } |
1356 | } | 1432 | } |
1433 | |||
1434 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { | ||
1435 | // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself. | ||
1436 | // We need a different order here. | ||
1437 | |||
1438 | fn walk_substs( | ||
1439 | db: &dyn HirDatabase, | ||
1440 | type_: &Type, | ||
1441 | substs: &Substs, | ||
1442 | cb: &mut impl FnMut(Type), | ||
1443 | ) { | ||
1444 | for ty in substs.iter() { | ||
1445 | walk_type(db, &type_.derived(ty.clone()), cb); | ||
1446 | } | ||
1447 | } | ||
1448 | |||
1449 | fn walk_bounds( | ||
1450 | db: &dyn HirDatabase, | ||
1451 | type_: &Type, | ||
1452 | bounds: &[GenericPredicate], | ||
1453 | cb: &mut impl FnMut(Type), | ||
1454 | ) { | ||
1455 | for pred in bounds { | ||
1456 | match pred { | ||
1457 | GenericPredicate::Implemented(trait_ref) => { | ||
1458 | cb(type_.clone()); | ||
1459 | walk_substs(db, type_, &trait_ref.substs, cb); | ||
1460 | } | ||
1461 | _ => (), | ||
1462 | } | ||
1463 | } | ||
1464 | } | ||
1465 | |||
1466 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { | ||
1467 | let ty = type_.ty.value.strip_references(); | ||
1468 | match ty { | ||
1469 | Ty::Apply(ApplicationTy { ctor, parameters }) => { | ||
1470 | match ctor { | ||
1471 | TypeCtor::Adt(_) => { | ||
1472 | cb(type_.derived(ty.clone())); | ||
1473 | } | ||
1474 | TypeCtor::AssociatedType(_) => { | ||
1475 | if let Some(_) = ty.associated_type_parent_trait(db) { | ||
1476 | cb(type_.derived(ty.clone())); | ||
1477 | } | ||
1478 | } | ||
1479 | _ => (), | ||
1480 | } | ||
1481 | |||
1482 | // adt params, tuples, etc... | ||
1483 | walk_substs(db, type_, parameters, cb); | ||
1484 | } | ||
1485 | Ty::Opaque(opaque_ty) => { | ||
1486 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1487 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1488 | } | ||
1489 | |||
1490 | walk_substs(db, type_, &opaque_ty.parameters, cb); | ||
1491 | } | ||
1492 | Ty::Placeholder(_) => { | ||
1493 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1494 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1495 | } | ||
1496 | } | ||
1497 | Ty::Dyn(bounds) => { | ||
1498 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); | ||
1499 | } | ||
1500 | |||
1501 | _ => (), | ||
1502 | } | ||
1503 | } | ||
1504 | |||
1505 | walk_type(db, self, &mut cb); | ||
1506 | } | ||
1357 | } | 1507 | } |
1358 | 1508 | ||
1359 | impl HirDisplay for Type { | 1509 | impl HirDisplay for Type { |
@@ -1421,8 +1571,8 @@ pub enum AttrDef { | |||
1421 | MacroDef(MacroDef), | 1571 | MacroDef(MacroDef), |
1422 | } | 1572 | } |
1423 | 1573 | ||
1424 | impl_froms!( | 1574 | impl_from!( |
1425 | AttrDef: Module, | 1575 | Module, |
1426 | Field, | 1576 | Field, |
1427 | Adt(Struct, Enum, Union), | 1577 | Adt(Struct, Enum, Union), |
1428 | EnumVariant, | 1578 | EnumVariant, |
@@ -1432,6 +1582,7 @@ impl_froms!( | |||
1432 | Trait, | 1582 | Trait, |
1433 | TypeAlias, | 1583 | TypeAlias, |
1434 | MacroDef | 1584 | MacroDef |
1585 | for AttrDef | ||
1435 | ); | 1586 | ); |
1436 | 1587 | ||
1437 | pub trait HasAttrs { | 1588 | pub trait HasAttrs { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index ec931b34f..1ad92a1f8 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -3,11 +3,11 @@ | |||
3 | pub use hir_def::db::{ | 3 | pub use hir_def::db::{ |
4 | AttrsQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQueryQuery, | 4 | AttrsQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQueryQuery, |
5 | CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, | 5 | CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, |
6 | ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternConstQuery, | 6 | ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, ImportMapQuery, |
7 | InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, InternImplQuery, | 7 | InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, |
8 | InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, InternUnionQuery, | 8 | InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, |
9 | LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, StaticDataQuery, StructDataQuery, | 9 | InternUnionQuery, ItemTreeQuery, LangItemQuery, ModuleLangItemsQuery, StaticDataQuery, |
10 | TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, | 10 | StructDataQuery, TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, |
11 | }; | 11 | }; |
12 | pub use hir_expand::db::{ | 12 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, | 13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, |
@@ -16,10 +16,10 @@ pub use hir_expand::db::{ | |||
16 | pub use hir_ty::db::{ | 16 | pub use hir_ty::db::{ |
17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, | 17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, |
18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, | 18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, |
19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsForTraitQuery, | 19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, InferQueryQuery, |
20 | ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, | 20 | InherentImplsInCrateQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, |
21 | InternTypeCtorQuery, InternTypeParamIdQuery, StructDatumQuery, TraitDatumQuery, | 21 | TraitDatumQuery, TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery, |
22 | TraitSolveQuery, TyQuery, ValueTyQuery, | 22 | ValueTyQuery, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | #[test] | 25 | #[test] |
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs index c82883d0c..11a0ecb8b 100644 --- a/crates/ra_hir/src/diagnostics.rs +++ b/crates/ra_hir/src/diagnostics.rs | |||
@@ -1,4 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | pub use hir_def::diagnostics::UnresolvedModule; | 2 | pub use hir_def::diagnostics::UnresolvedModule; |
3 | pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; | 3 | pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; |
4 | pub use hir_ty::diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField}; | 4 | pub use hir_ty::diagnostics::{ |
5 | MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField, | ||
6 | }; | ||
diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs index 63b8fd369..76c32fc17 100644 --- a/crates/ra_hir/src/has_source.rs +++ b/crates/ra_hir/src/has_source.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use either::Either; | 3 | use either::Either; |
4 | use hir_def::{ | 4 | use hir_def::{ |
5 | nameres::ModuleSource, | 5 | nameres::{ModuleOrigin, ModuleSource}, |
6 | src::{HasChildSource, HasSource as _}, | 6 | src::{HasChildSource, HasSource as _}, |
7 | Lookup, VariantId, | 7 | Lookup, VariantId, |
8 | }; | 8 | }; |
@@ -29,6 +29,14 @@ impl Module { | |||
29 | def_map[self.id.local_id].definition_source(db.upcast()) | 29 | def_map[self.id.local_id].definition_source(db.upcast()) |
30 | } | 30 | } |
31 | 31 | ||
32 | pub fn is_mod_rs(self, db: &dyn HirDatabase) -> bool { | ||
33 | let def_map = db.crate_def_map(self.id.krate); | ||
34 | match def_map[self.id.local_id].origin { | ||
35 | ModuleOrigin::File { is_mod_rs, .. } => is_mod_rs, | ||
36 | _ => false, | ||
37 | } | ||
38 | } | ||
39 | |||
32 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. | 40 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. |
33 | /// `None` for the crate root. | 41 | /// `None` for the crate root. |
34 | pub fn declaration_source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Module>> { | 42 | pub fn declaration_source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Module>> { |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 3364a822f..cf7134923 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -19,25 +19,6 @@ | |||
19 | 19 | ||
20 | #![recursion_limit = "512"] | 20 | #![recursion_limit = "512"] |
21 | 21 | ||
22 | macro_rules! impl_froms { | ||
23 | ($e:ident: $($v:ident $(($($sv:ident),*))?),*$(,)?) => { | ||
24 | $( | ||
25 | impl From<$v> for $e { | ||
26 | fn from(it: $v) -> $e { | ||
27 | $e::$v(it) | ||
28 | } | ||
29 | } | ||
30 | $($( | ||
31 | impl From<$sv> for $e { | ||
32 | fn from(it: $sv) -> $e { | ||
33 | $e::$v($v::$sv(it)) | ||
34 | } | ||
35 | } | ||
36 | )*)? | ||
37 | )* | ||
38 | } | ||
39 | } | ||
40 | |||
41 | mod semantics; | 22 | mod semantics; |
42 | pub mod db; | 23 | pub mod db; |
43 | mod source_analyzer; | 24 | mod source_analyzer; |
@@ -74,4 +55,4 @@ pub use hir_expand::{ | |||
74 | hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, | 55 | hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, |
75 | MacroFile, Origin, | 56 | MacroFile, Origin, |
76 | }; | 57 | }; |
77 | pub use hir_ty::{display::HirDisplay, CallableDef}; | 58 | pub use hir_ty::{display::HirDisplay, CallableDefId}; |
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 7c1f79f27..155b666d7 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -6,9 +6,9 @@ use std::{cell::RefCell, fmt, iter::successors}; | |||
6 | 6 | ||
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | resolver::{self, HasResolver, Resolver}, | 8 | resolver::{self, HasResolver, Resolver}, |
9 | AsMacroCall, TraitId, | 9 | AsMacroCall, TraitId, VariantId, |
10 | }; | 10 | }; |
11 | use hir_expand::{hygiene::Hygiene, ExpansionInfo}; | 11 | use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; |
12 | use hir_ty::associated_type_shorthand_candidates; | 12 | use hir_ty::associated_type_shorthand_candidates; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use ra_db::{FileId, FileRange}; | 14 | use ra_db::{FileId, FileRange}; |
@@ -25,7 +25,7 @@ use crate::{ | |||
25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, | 26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, |
27 | AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, | 27 | AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, |
28 | Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, | 28 | Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, |
29 | }; | 29 | }; |
30 | use resolver::TypeNs; | 30 | use resolver::TypeNs; |
31 | 31 | ||
@@ -83,6 +83,11 @@ impl PathResolution { | |||
83 | /// Primary API to get semantic information, like types, from syntax trees. | 83 | /// Primary API to get semantic information, like types, from syntax trees. |
84 | pub struct Semantics<'db, DB> { | 84 | pub struct Semantics<'db, DB> { |
85 | pub db: &'db DB, | 85 | pub db: &'db DB, |
86 | imp: SemanticsImpl<'db>, | ||
87 | } | ||
88 | |||
89 | pub struct SemanticsImpl<'db> { | ||
90 | pub db: &'db dyn HirDatabase, | ||
86 | s2d_cache: RefCell<SourceToDefCache>, | 91 | s2d_cache: RefCell<SourceToDefCache>, |
87 | cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>, | 92 | cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>, |
88 | } | 93 | } |
@@ -95,16 +100,187 @@ impl<DB> fmt::Debug for Semantics<'_, DB> { | |||
95 | 100 | ||
96 | impl<'db, DB: HirDatabase> Semantics<'db, DB> { | 101 | impl<'db, DB: HirDatabase> Semantics<'db, DB> { |
97 | pub fn new(db: &DB) -> Semantics<DB> { | 102 | pub fn new(db: &DB) -> Semantics<DB> { |
98 | Semantics { db, s2d_cache: Default::default(), cache: Default::default() } | 103 | let impl_ = SemanticsImpl::new(db); |
104 | Semantics { db, imp: impl_ } | ||
99 | } | 105 | } |
100 | 106 | ||
101 | pub fn parse(&self, file_id: FileId) -> ast::SourceFile { | 107 | pub fn parse(&self, file_id: FileId) -> ast::SourceFile { |
108 | self.imp.parse(file_id) | ||
109 | } | ||
110 | |||
111 | pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST { | ||
112 | let file_id = d.source().file_id; | ||
113 | let root = self.db.parse_or_expand(file_id).unwrap(); | ||
114 | self.imp.cache(root, file_id); | ||
115 | d.ast(self.db.upcast()) | ||
116 | } | ||
117 | |||
118 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { | ||
119 | self.imp.expand(macro_call) | ||
120 | } | ||
121 | |||
122 | pub fn expand_hypothetical( | ||
123 | &self, | ||
124 | actual_macro_call: &ast::MacroCall, | ||
125 | hypothetical_args: &ast::TokenTree, | ||
126 | token_to_map: SyntaxToken, | ||
127 | ) -> Option<(SyntaxNode, SyntaxToken)> { | ||
128 | self.imp.expand_hypothetical(actual_macro_call, hypothetical_args, token_to_map) | ||
129 | } | ||
130 | |||
131 | pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { | ||
132 | self.imp.descend_into_macros(token) | ||
133 | } | ||
134 | |||
135 | pub fn descend_node_at_offset<N: ast::AstNode>( | ||
136 | &self, | ||
137 | node: &SyntaxNode, | ||
138 | offset: TextSize, | ||
139 | ) -> Option<N> { | ||
140 | self.imp.descend_node_at_offset(node, offset).find_map(N::cast) | ||
141 | } | ||
142 | |||
143 | pub fn original_range(&self, node: &SyntaxNode) -> FileRange { | ||
144 | self.imp.original_range(node) | ||
145 | } | ||
146 | |||
147 | pub fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { | ||
148 | self.imp.diagnostics_range(diagnostics) | ||
149 | } | ||
150 | |||
151 | pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { | ||
152 | self.imp.ancestors_with_macros(node) | ||
153 | } | ||
154 | |||
155 | pub fn ancestors_at_offset_with_macros( | ||
156 | &self, | ||
157 | node: &SyntaxNode, | ||
158 | offset: TextSize, | ||
159 | ) -> impl Iterator<Item = SyntaxNode> + '_ { | ||
160 | self.imp.ancestors_at_offset_with_macros(node, offset) | ||
161 | } | ||
162 | |||
163 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*, | ||
164 | /// search up until it is of the target AstNode type | ||
165 | pub fn find_node_at_offset_with_macros<N: AstNode>( | ||
166 | &self, | ||
167 | node: &SyntaxNode, | ||
168 | offset: TextSize, | ||
169 | ) -> Option<N> { | ||
170 | self.imp.ancestors_at_offset_with_macros(node, offset).find_map(N::cast) | ||
171 | } | ||
172 | |||
173 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *MacroCall*, | ||
174 | /// descend it and find again | ||
175 | pub fn find_node_at_offset_with_descend<N: AstNode>( | ||
176 | &self, | ||
177 | node: &SyntaxNode, | ||
178 | offset: TextSize, | ||
179 | ) -> Option<N> { | ||
180 | if let Some(it) = find_node_at_offset(&node, offset) { | ||
181 | return Some(it); | ||
182 | } | ||
183 | |||
184 | self.imp.descend_node_at_offset(node, offset).find_map(N::cast) | ||
185 | } | ||
186 | |||
187 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { | ||
188 | self.imp.type_of_expr(expr) | ||
189 | } | ||
190 | |||
191 | pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { | ||
192 | self.imp.type_of_pat(pat) | ||
193 | } | ||
194 | |||
195 | pub fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { | ||
196 | self.imp.type_of_self(param) | ||
197 | } | ||
198 | |||
199 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | ||
200 | self.imp.resolve_method_call(call) | ||
201 | } | ||
202 | |||
203 | pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { | ||
204 | self.imp.resolve_field(field) | ||
205 | } | ||
206 | |||
207 | pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<(Field, Option<Local>)> { | ||
208 | self.imp.resolve_record_field(field) | ||
209 | } | ||
210 | |||
211 | pub fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> { | ||
212 | self.imp.resolve_record_field_pat(field) | ||
213 | } | ||
214 | |||
215 | pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { | ||
216 | self.imp.resolve_macro_call(macro_call) | ||
217 | } | ||
218 | |||
219 | pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> { | ||
220 | self.imp.resolve_path(path) | ||
221 | } | ||
222 | |||
223 | pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantDef> { | ||
224 | self.imp.resolve_variant(record_lit).map(VariantDef::from) | ||
225 | } | ||
226 | |||
227 | pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { | ||
228 | self.imp.lower_path(path) | ||
229 | } | ||
230 | |||
231 | pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> { | ||
232 | self.imp.resolve_bind_pat_to_const(pat) | ||
233 | } | ||
234 | |||
235 | // FIXME: use this instead? | ||
236 | // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>; | ||
237 | |||
238 | pub fn record_literal_missing_fields(&self, literal: &ast::RecordLit) -> Vec<(Field, Type)> { | ||
239 | self.imp.record_literal_missing_fields(literal) | ||
240 | } | ||
241 | |||
242 | pub fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> { | ||
243 | self.imp.record_pattern_missing_fields(pattern) | ||
244 | } | ||
245 | |||
246 | pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> { | ||
247 | let src = self.imp.find_file(src.syntax().clone()).with_value(src).cloned(); | ||
248 | T::to_def(&self.imp, src) | ||
249 | } | ||
250 | |||
251 | pub fn to_module_def(&self, file: FileId) -> Option<Module> { | ||
252 | self.imp.to_module_def(file) | ||
253 | } | ||
254 | |||
255 | pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { | ||
256 | self.imp.scope(node) | ||
257 | } | ||
258 | |||
259 | pub fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { | ||
260 | self.imp.scope_at_offset(node, offset) | ||
261 | } | ||
262 | |||
263 | pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { | ||
264 | self.imp.scope_for_def(def) | ||
265 | } | ||
266 | |||
267 | pub fn assert_contains_node(&self, node: &SyntaxNode) { | ||
268 | self.imp.assert_contains_node(node) | ||
269 | } | ||
270 | } | ||
271 | |||
272 | impl<'db> SemanticsImpl<'db> { | ||
273 | fn new(db: &'db dyn HirDatabase) -> Self { | ||
274 | Self { db, s2d_cache: Default::default(), cache: Default::default() } | ||
275 | } | ||
276 | |||
277 | fn parse(&self, file_id: FileId) -> ast::SourceFile { | ||
102 | let tree = self.db.parse(file_id).tree(); | 278 | let tree = self.db.parse(file_id).tree(); |
103 | self.cache(tree.syntax().clone(), file_id.into()); | 279 | self.cache(tree.syntax().clone(), file_id.into()); |
104 | tree | 280 | tree |
105 | } | 281 | } |
106 | 282 | ||
107 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { | 283 | fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { |
108 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); | 284 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); |
109 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); | 285 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); |
110 | let file_id = sa.expand(self.db, macro_call)?; | 286 | let file_id = sa.expand(self.db, macro_call)?; |
@@ -113,7 +289,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
113 | Some(node) | 289 | Some(node) |
114 | } | 290 | } |
115 | 291 | ||
116 | pub fn expand_hypothetical( | 292 | fn expand_hypothetical( |
117 | &self, | 293 | &self, |
118 | actual_macro_call: &ast::MacroCall, | 294 | actual_macro_call: &ast::MacroCall, |
119 | hypothetical_args: &ast::TokenTree, | 295 | hypothetical_args: &ast::TokenTree, |
@@ -122,12 +298,19 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
122 | let macro_call = | 298 | let macro_call = |
123 | self.find_file(actual_macro_call.syntax().clone()).with_value(actual_macro_call); | 299 | self.find_file(actual_macro_call.syntax().clone()).with_value(actual_macro_call); |
124 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); | 300 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); |
125 | let macro_call_id = macro_call | 301 | let krate = sa.resolver.krate()?; |
126 | .as_call_id(self.db, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?; | 302 | let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { |
127 | hir_expand::db::expand_hypothetical(self.db, macro_call_id, hypothetical_args, token_to_map) | 303 | sa.resolver.resolve_path_as_macro(self.db.upcast(), &path) |
128 | } | 304 | })?; |
129 | 305 | hir_expand::db::expand_hypothetical( | |
130 | pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { | 306 | self.db.upcast(), |
307 | macro_call_id, | ||
308 | hypothetical_args, | ||
309 | token_to_map, | ||
310 | ) | ||
311 | } | ||
312 | |||
313 | fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { | ||
131 | let parent = token.parent(); | 314 | let parent = token.parent(); |
132 | let parent = self.find_file(parent); | 315 | let parent = self.find_file(parent); |
133 | let sa = self.analyze2(parent.as_ref(), None); | 316 | let sa = self.analyze2(parent.as_ref(), None); |
@@ -139,7 +322,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
139 | return None; | 322 | return None; |
140 | } | 323 | } |
141 | let file_id = sa.expand(self.db, token.with_value(¯o_call))?; | 324 | let file_id = sa.expand(self.db, token.with_value(¯o_call))?; |
142 | let token = file_id.expansion_info(self.db)?.map_token_down(token.as_ref())?; | 325 | let token = file_id.expansion_info(self.db.upcast())?.map_token_down(token.as_ref())?; |
143 | 326 | ||
144 | self.cache(find_root(&token.value.parent()), token.file_id); | 327 | self.cache(find_root(&token.value.parent()), token.file_id); |
145 | 328 | ||
@@ -151,35 +334,36 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
151 | token.value | 334 | token.value |
152 | } | 335 | } |
153 | 336 | ||
154 | pub fn descend_node_at_offset<N: ast::AstNode>( | 337 | fn descend_node_at_offset( |
155 | &self, | 338 | &self, |
156 | node: &SyntaxNode, | 339 | node: &SyntaxNode, |
157 | offset: TextSize, | 340 | offset: TextSize, |
158 | ) -> Option<N> { | 341 | ) -> impl Iterator<Item = SyntaxNode> + '_ { |
159 | // Handle macro token cases | 342 | // Handle macro token cases |
160 | node.token_at_offset(offset) | 343 | node.token_at_offset(offset) |
161 | .map(|token| self.descend_into_macros(token)) | 344 | .map(|token| self.descend_into_macros(token)) |
162 | .find_map(|it| self.ancestors_with_macros(it.parent()).find_map(N::cast)) | 345 | .map(|it| self.ancestors_with_macros(it.parent())) |
346 | .flatten() | ||
163 | } | 347 | } |
164 | 348 | ||
165 | pub fn original_range(&self, node: &SyntaxNode) -> FileRange { | 349 | fn original_range(&self, node: &SyntaxNode) -> FileRange { |
166 | let node = self.find_file(node.clone()); | 350 | let node = self.find_file(node.clone()); |
167 | original_range(self.db, node.as_ref()) | 351 | original_range(self.db, node.as_ref()) |
168 | } | 352 | } |
169 | 353 | ||
170 | pub fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { | 354 | fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { |
171 | let src = diagnostics.source(); | 355 | let src = diagnostics.source(); |
172 | let root = self.db.parse_or_expand(src.file_id).unwrap(); | 356 | let root = self.db.parse_or_expand(src.file_id).unwrap(); |
173 | let node = src.value.to_node(&root); | 357 | let node = src.value.to_node(&root); |
174 | original_range(self.db, src.with_value(&node)) | 358 | original_range(self.db, src.with_value(&node)) |
175 | } | 359 | } |
176 | 360 | ||
177 | pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { | 361 | fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { |
178 | let node = self.find_file(node); | 362 | let node = self.find_file(node); |
179 | node.ancestors_with_macros(self.db).map(|it| it.value) | 363 | node.ancestors_with_macros(self.db.upcast()).map(|it| it.value) |
180 | } | 364 | } |
181 | 365 | ||
182 | pub fn ancestors_at_offset_with_macros( | 366 | fn ancestors_at_offset_with_macros( |
183 | &self, | 367 | &self, |
184 | node: &SyntaxNode, | 368 | node: &SyntaxNode, |
185 | offset: TextSize, | 369 | offset: TextSize, |
@@ -189,116 +373,93 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
189 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) | 373 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) |
190 | } | 374 | } |
191 | 375 | ||
192 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*, | 376 | fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { |
193 | /// search up until it is of the target AstNode type | 377 | self.analyze(expr.syntax()).type_of_expr(self.db, &expr) |
194 | pub fn find_node_at_offset_with_macros<N: AstNode>( | ||
195 | &self, | ||
196 | node: &SyntaxNode, | ||
197 | offset: TextSize, | ||
198 | ) -> Option<N> { | ||
199 | self.ancestors_at_offset_with_macros(node, offset).find_map(N::cast) | ||
200 | } | 378 | } |
201 | 379 | ||
202 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *MacroCall*, | 380 | fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { |
203 | /// descend it and find again | 381 | self.analyze(pat.syntax()).type_of_pat(self.db, &pat) |
204 | pub fn find_node_at_offset_with_descend<N: AstNode>( | ||
205 | &self, | ||
206 | node: &SyntaxNode, | ||
207 | offset: TextSize, | ||
208 | ) -> Option<N> { | ||
209 | if let Some(it) = find_node_at_offset(&node, offset) { | ||
210 | return Some(it); | ||
211 | } | ||
212 | self.descend_node_at_offset(&node, offset) | ||
213 | } | 382 | } |
214 | 383 | ||
215 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { | 384 | fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { |
216 | self.analyze(expr.syntax()).type_of(self.db, &expr) | 385 | self.analyze(param.syntax()).type_of_self(self.db, ¶m) |
217 | } | 386 | } |
218 | 387 | ||
219 | pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { | 388 | fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { |
220 | self.analyze(pat.syntax()).type_of_pat(self.db, &pat) | ||
221 | } | ||
222 | |||
223 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | ||
224 | self.analyze(call.syntax()).resolve_method_call(self.db, call) | 389 | self.analyze(call.syntax()).resolve_method_call(self.db, call) |
225 | } | 390 | } |
226 | 391 | ||
227 | pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { | 392 | fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { |
228 | self.analyze(field.syntax()).resolve_field(self.db, field) | 393 | self.analyze(field.syntax()).resolve_field(self.db, field) |
229 | } | 394 | } |
230 | 395 | ||
231 | pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<(Field, Option<Local>)> { | 396 | fn resolve_record_field(&self, field: &ast::RecordField) -> Option<(Field, Option<Local>)> { |
232 | self.analyze(field.syntax()).resolve_record_field(self.db, field) | 397 | self.analyze(field.syntax()).resolve_record_field(self.db, field) |
233 | } | 398 | } |
234 | 399 | ||
235 | pub fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> { | 400 | fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> { |
236 | self.analyze(field.syntax()).resolve_record_field_pat(self.db, field) | 401 | self.analyze(field.syntax()).resolve_record_field_pat(self.db, field) |
237 | } | 402 | } |
238 | 403 | ||
239 | pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { | 404 | fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { |
240 | let sa = self.analyze(macro_call.syntax()); | 405 | let sa = self.analyze(macro_call.syntax()); |
241 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); | 406 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); |
242 | sa.resolve_macro_call(self.db, macro_call) | 407 | sa.resolve_macro_call(self.db, macro_call) |
243 | } | 408 | } |
244 | 409 | ||
245 | pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> { | 410 | fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> { |
246 | self.analyze(path.syntax()).resolve_path(self.db, path) | 411 | self.analyze(path.syntax()).resolve_path(self.db, path) |
247 | } | 412 | } |
248 | 413 | ||
249 | pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { | 414 | fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> { |
415 | self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) | ||
416 | } | ||
417 | |||
418 | fn lower_path(&self, path: &ast::Path) -> Option<Path> { | ||
250 | let src = self.find_file(path.syntax().clone()); | 419 | let src = self.find_file(path.syntax().clone()); |
251 | Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) | 420 | Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) |
252 | } | 421 | } |
253 | 422 | ||
254 | pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> { | 423 | fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> { |
255 | self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat) | 424 | self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat) |
256 | } | 425 | } |
257 | 426 | ||
258 | // FIXME: use this instead? | 427 | fn record_literal_missing_fields(&self, literal: &ast::RecordLit) -> Vec<(Field, Type)> { |
259 | // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>; | ||
260 | |||
261 | pub fn record_literal_missing_fields(&self, literal: &ast::RecordLit) -> Vec<(Field, Type)> { | ||
262 | self.analyze(literal.syntax()) | 428 | self.analyze(literal.syntax()) |
263 | .record_literal_missing_fields(self.db, literal) | 429 | .record_literal_missing_fields(self.db, literal) |
264 | .unwrap_or_default() | 430 | .unwrap_or_default() |
265 | } | 431 | } |
266 | 432 | ||
267 | pub fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> { | 433 | fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> { |
268 | self.analyze(pattern.syntax()) | 434 | self.analyze(pattern.syntax()) |
269 | .record_pattern_missing_fields(self.db, pattern) | 435 | .record_pattern_missing_fields(self.db, pattern) |
270 | .unwrap_or_default() | 436 | .unwrap_or_default() |
271 | } | 437 | } |
272 | 438 | ||
273 | pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> { | ||
274 | let src = self.find_file(src.syntax().clone()).with_value(src).cloned(); | ||
275 | T::to_def(self, src) | ||
276 | } | ||
277 | |||
278 | fn with_ctx<F: FnOnce(&mut SourceToDefCtx) -> T, T>(&self, f: F) -> T { | 439 | fn with_ctx<F: FnOnce(&mut SourceToDefCtx) -> T, T>(&self, f: F) -> T { |
279 | let mut cache = self.s2d_cache.borrow_mut(); | 440 | let mut cache = self.s2d_cache.borrow_mut(); |
280 | let mut ctx = SourceToDefCtx { db: self.db, cache: &mut *cache }; | 441 | let mut ctx = SourceToDefCtx { db: self.db, cache: &mut *cache }; |
281 | f(&mut ctx) | 442 | f(&mut ctx) |
282 | } | 443 | } |
283 | 444 | ||
284 | pub fn to_module_def(&self, file: FileId) -> Option<Module> { | 445 | fn to_module_def(&self, file: FileId) -> Option<Module> { |
285 | self.with_ctx(|ctx| ctx.file_to_def(file)).map(Module::from) | 446 | self.with_ctx(|ctx| ctx.file_to_def(file)).map(Module::from) |
286 | } | 447 | } |
287 | 448 | ||
288 | pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db, DB> { | 449 | fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { |
289 | let node = self.find_file(node.clone()); | 450 | let node = self.find_file(node.clone()); |
290 | let resolver = self.analyze2(node.as_ref(), None).resolver; | 451 | let resolver = self.analyze2(node.as_ref(), None).resolver; |
291 | SemanticsScope { db: self.db, resolver } | 452 | SemanticsScope { db: self.db, resolver } |
292 | } | 453 | } |
293 | 454 | ||
294 | pub fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db, DB> { | 455 | fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { |
295 | let node = self.find_file(node.clone()); | 456 | let node = self.find_file(node.clone()); |
296 | let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver; | 457 | let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver; |
297 | SemanticsScope { db: self.db, resolver } | 458 | SemanticsScope { db: self.db, resolver } |
298 | } | 459 | } |
299 | 460 | ||
300 | pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db, DB> { | 461 | fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { |
301 | let resolver = def.id.resolver(self.db); | 462 | let resolver = def.id.resolver(self.db.upcast()); |
302 | SemanticsScope { db: self.db, resolver } | 463 | SemanticsScope { db: self.db, resolver } |
303 | } | 464 | } |
304 | 465 | ||
@@ -319,12 +480,13 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
319 | ChildContainer::DefWithBodyId(def) => { | 480 | ChildContainer::DefWithBodyId(def) => { |
320 | return SourceAnalyzer::new_for_body(self.db, def, src, offset) | 481 | return SourceAnalyzer::new_for_body(self.db, def, src, offset) |
321 | } | 482 | } |
322 | ChildContainer::TraitId(it) => it.resolver(self.db), | 483 | ChildContainer::TraitId(it) => it.resolver(self.db.upcast()), |
323 | ChildContainer::ImplId(it) => it.resolver(self.db), | 484 | ChildContainer::ImplId(it) => it.resolver(self.db.upcast()), |
324 | ChildContainer::ModuleId(it) => it.resolver(self.db), | 485 | ChildContainer::ModuleId(it) => it.resolver(self.db.upcast()), |
325 | ChildContainer::EnumId(it) => it.resolver(self.db), | 486 | ChildContainer::EnumId(it) => it.resolver(self.db.upcast()), |
326 | ChildContainer::VariantId(it) => it.resolver(self.db), | 487 | ChildContainer::VariantId(it) => it.resolver(self.db.upcast()), |
327 | ChildContainer::GenericDefId(it) => it.resolver(self.db), | 488 | ChildContainer::TypeAliasId(it) => it.resolver(self.db.upcast()), |
489 | ChildContainer::GenericDefId(it) => it.resolver(self.db.upcast()), | ||
328 | }; | 490 | }; |
329 | SourceAnalyzer::new_for_resolver(resolver, src) | 491 | SourceAnalyzer::new_for_resolver(resolver, src) |
330 | } | 492 | } |
@@ -336,7 +498,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
336 | assert!(prev == None || prev == Some(file_id)) | 498 | assert!(prev == None || prev == Some(file_id)) |
337 | } | 499 | } |
338 | 500 | ||
339 | pub fn assert_contains_node(&self, node: &SyntaxNode) { | 501 | fn assert_contains_node(&self, node: &SyntaxNode) { |
340 | self.find_file(node.clone()); | 502 | self.find_file(node.clone()); |
341 | } | 503 | } |
342 | 504 | ||
@@ -370,14 +532,14 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
370 | pub trait ToDef: AstNode + Clone { | 532 | pub trait ToDef: AstNode + Clone { |
371 | type Def; | 533 | type Def; |
372 | 534 | ||
373 | fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: InFile<Self>) -> Option<Self::Def>; | 535 | fn to_def(sema: &SemanticsImpl, src: InFile<Self>) -> Option<Self::Def>; |
374 | } | 536 | } |
375 | 537 | ||
376 | macro_rules! to_def_impls { | 538 | macro_rules! to_def_impls { |
377 | ($(($def:path, $ast:path, $meth:ident)),* ,) => {$( | 539 | ($(($def:path, $ast:path, $meth:ident)),* ,) => {$( |
378 | impl ToDef for $ast { | 540 | impl ToDef for $ast { |
379 | type Def = $def; | 541 | type Def = $def; |
380 | fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: InFile<Self>) -> Option<Self::Def> { | 542 | fn to_def(sema: &SemanticsImpl, src: InFile<Self>) -> Option<Self::Def> { |
381 | sema.with_ctx(|ctx| ctx.$meth(src)).map(<$def>::from) | 543 | sema.with_ctx(|ctx| ctx.$meth(src)).map(<$def>::from) |
382 | } | 544 | } |
383 | } | 545 | } |
@@ -407,12 +569,13 @@ fn find_root(node: &SyntaxNode) -> SyntaxNode { | |||
407 | node.ancestors().last().unwrap() | 569 | node.ancestors().last().unwrap() |
408 | } | 570 | } |
409 | 571 | ||
410 | pub struct SemanticsScope<'a, DB> { | 572 | #[derive(Debug)] |
411 | pub db: &'a DB, | 573 | pub struct SemanticsScope<'a> { |
574 | pub db: &'a dyn HirDatabase, | ||
412 | resolver: Resolver, | 575 | resolver: Resolver, |
413 | } | 576 | } |
414 | 577 | ||
415 | impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> { | 578 | impl<'a> SemanticsScope<'a> { |
416 | pub fn module(&self) -> Option<Module> { | 579 | pub fn module(&self) -> Option<Module> { |
417 | Some(Module { id: self.resolver.module()? }) | 580 | Some(Module { id: self.resolver.module()? }) |
418 | } | 581 | } |
@@ -421,13 +584,13 @@ impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> { | |||
421 | // FIXME: rename to visible_traits to not repeat scope? | 584 | // FIXME: rename to visible_traits to not repeat scope? |
422 | pub fn traits_in_scope(&self) -> FxHashSet<TraitId> { | 585 | pub fn traits_in_scope(&self) -> FxHashSet<TraitId> { |
423 | let resolver = &self.resolver; | 586 | let resolver = &self.resolver; |
424 | resolver.traits_in_scope(self.db) | 587 | resolver.traits_in_scope(self.db.upcast()) |
425 | } | 588 | } |
426 | 589 | ||
427 | pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) { | 590 | pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) { |
428 | let resolver = &self.resolver; | 591 | let resolver = &self.resolver; |
429 | 592 | ||
430 | resolver.process_all_names(self.db, &mut |name, def| { | 593 | resolver.process_all_names(self.db.upcast(), &mut |name, def| { |
431 | let def = match def { | 594 | let def = match def { |
432 | resolver::ScopeDef::PerNs(it) => { | 595 | resolver::ScopeDef::PerNs(it) => { |
433 | let items = ScopeDef::all_items(it); | 596 | let items = ScopeDef::all_items(it); |
diff --git a/crates/ra_hir/src/semantics/source_to_def.rs b/crates/ra_hir/src/semantics/source_to_def.rs index 8af64fdc1..42e5a1bdb 100644 --- a/crates/ra_hir/src/semantics/source_to_def.rs +++ b/crates/ra_hir/src/semantics/source_to_def.rs | |||
@@ -16,6 +16,7 @@ use ra_syntax::{ | |||
16 | match_ast, AstNode, SyntaxNode, | 16 | match_ast, AstNode, SyntaxNode, |
17 | }; | 17 | }; |
18 | use rustc_hash::FxHashMap; | 18 | use rustc_hash::FxHashMap; |
19 | use stdx::impl_from; | ||
19 | 20 | ||
20 | use crate::{db::HirDatabase, InFile, MacroDefId}; | 21 | use crate::{db::HirDatabase, InFile, MacroDefId}; |
21 | 22 | ||
@@ -194,6 +195,10 @@ impl SourceToDefCtx<'_, '_> { | |||
194 | let def = self.const_to_def(container.with_value(it))?; | 195 | let def = self.const_to_def(container.with_value(it))?; |
195 | DefWithBodyId::from(def).into() | 196 | DefWithBodyId::from(def).into() |
196 | }, | 197 | }, |
198 | ast::TypeAliasDef(it) => { | ||
199 | let def = self.type_alias_to_def(container.with_value(it))?; | ||
200 | def.into() | ||
201 | }, | ||
197 | _ => continue, | 202 | _ => continue, |
198 | } | 203 | } |
199 | }; | 204 | }; |
@@ -246,19 +251,21 @@ pub(crate) enum ChildContainer { | |||
246 | ImplId(ImplId), | 251 | ImplId(ImplId), |
247 | EnumId(EnumId), | 252 | EnumId(EnumId), |
248 | VariantId(VariantId), | 253 | VariantId(VariantId), |
254 | TypeAliasId(TypeAliasId), | ||
249 | /// XXX: this might be the same def as, for example an `EnumId`. However, | 255 | /// XXX: this might be the same def as, for example an `EnumId`. However, |
250 | /// here the children generic parameters, and not, eg enum variants. | 256 | /// here the children generic parameters, and not, eg enum variants. |
251 | GenericDefId(GenericDefId), | 257 | GenericDefId(GenericDefId), |
252 | } | 258 | } |
253 | impl_froms! { | 259 | impl_from! { |
254 | ChildContainer: | ||
255 | DefWithBodyId, | 260 | DefWithBodyId, |
256 | ModuleId, | 261 | ModuleId, |
257 | TraitId, | 262 | TraitId, |
258 | ImplId, | 263 | ImplId, |
259 | EnumId, | 264 | EnumId, |
260 | VariantId, | 265 | VariantId, |
266 | TypeAliasId, | ||
261 | GenericDefId | 267 | GenericDefId |
268 | for ChildContainer | ||
262 | } | 269 | } |
263 | 270 | ||
264 | impl ChildContainer { | 271 | impl ChildContainer { |
@@ -271,6 +278,7 @@ impl ChildContainer { | |||
271 | ChildContainer::ImplId(it) => it.child_by_source(db), | 278 | ChildContainer::ImplId(it) => it.child_by_source(db), |
272 | ChildContainer::EnumId(it) => it.child_by_source(db), | 279 | ChildContainer::EnumId(it) => it.child_by_source(db), |
273 | ChildContainer::VariantId(it) => it.child_by_source(db), | 280 | ChildContainer::VariantId(it) => it.child_by_source(db), |
281 | ChildContainer::TypeAliasId(_) => DynMap::default(), | ||
274 | ChildContainer::GenericDefId(it) => it.child_by_source(db), | 282 | ChildContainer::GenericDefId(it) => it.child_by_source(db), |
275 | } | 283 | } |
276 | } | 284 | } |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 4b509f07c..ecb54f653 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -18,7 +18,7 @@ use hir_def::{ | |||
18 | }; | 18 | }; |
19 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; | 19 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; |
20 | use hir_ty::{ | 20 | use hir_ty::{ |
21 | expr::{record_literal_missing_fields, record_pattern_missing_fields}, | 21 | diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, |
22 | InferenceResult, Substs, Ty, | 22 | InferenceResult, Substs, Ty, |
23 | }; | 23 | }; |
24 | use ra_syntax::{ | 24 | use ra_syntax::{ |
@@ -115,7 +115,7 @@ impl SourceAnalyzer { | |||
115 | Some(res) | 115 | Some(res) |
116 | } | 116 | } |
117 | 117 | ||
118 | pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { | 118 | pub(crate) fn type_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { |
119 | let expr_id = self.expr_id(db, expr)?; | 119 | let expr_id = self.expr_id(db, expr)?; |
120 | let ty = self.infer.as_ref()?[expr_id].clone(); | 120 | let ty = self.infer.as_ref()?[expr_id].clone(); |
121 | Type::new_with_resolver(db, &self.resolver, ty) | 121 | Type::new_with_resolver(db, &self.resolver, ty) |
@@ -127,6 +127,17 @@ impl SourceAnalyzer { | |||
127 | Type::new_with_resolver(db, &self.resolver, ty) | 127 | Type::new_with_resolver(db, &self.resolver, ty) |
128 | } | 128 | } |
129 | 129 | ||
130 | pub(crate) fn type_of_self( | ||
131 | &self, | ||
132 | db: &dyn HirDatabase, | ||
133 | param: &ast::SelfParam, | ||
134 | ) -> Option<Type> { | ||
135 | let src = InFile { file_id: self.file_id, value: param }; | ||
136 | let pat_id = self.body_source_map.as_ref()?.node_self_param(src)?; | ||
137 | let ty = self.infer.as_ref()?[pat_id].clone(); | ||
138 | Type::new_with_resolver(db, &self.resolver, ty) | ||
139 | } | ||
140 | |||
130 | pub(crate) fn resolve_method_call( | 141 | pub(crate) fn resolve_method_call( |
131 | &self, | 142 | &self, |
132 | db: &dyn HirDatabase, | 143 | db: &dyn HirDatabase, |
@@ -216,13 +227,43 @@ impl SourceAnalyzer { | |||
216 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { | 227 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { |
217 | return Some(PathResolution::AssocItem(assoc.into())); | 228 | return Some(PathResolution::AssocItem(assoc.into())); |
218 | } | 229 | } |
230 | if let Some(VariantId::EnumVariantId(variant)) = | ||
231 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) | ||
232 | { | ||
233 | return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); | ||
234 | } | ||
219 | } | 235 | } |
236 | |||
220 | if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { | 237 | if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { |
221 | let pat_id = self.pat_id(&path_pat.into())?; | 238 | let pat_id = self.pat_id(&path_pat.into())?; |
222 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { | 239 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { |
223 | return Some(PathResolution::AssocItem(assoc.into())); | 240 | return Some(PathResolution::AssocItem(assoc.into())); |
224 | } | 241 | } |
242 | if let Some(VariantId::EnumVariantId(variant)) = | ||
243 | self.infer.as_ref()?.variant_resolution_for_pat(pat_id) | ||
244 | { | ||
245 | return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordLit::cast) { | ||
250 | let expr_id = self.expr_id(db, &rec_lit.into())?; | ||
251 | if let Some(VariantId::EnumVariantId(variant)) = | ||
252 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) | ||
253 | { | ||
254 | return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); | ||
255 | } | ||
256 | } | ||
257 | |||
258 | if let Some(rec_pat) = path.syntax().parent().and_then(ast::RecordPat::cast) { | ||
259 | let pat_id = self.pat_id(&rec_pat.into())?; | ||
260 | if let Some(VariantId::EnumVariantId(variant)) = | ||
261 | self.infer.as_ref()?.variant_resolution_for_pat(pat_id) | ||
262 | { | ||
263 | return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into()))); | ||
264 | } | ||
225 | } | 265 | } |
266 | |||
226 | // This must be a normal source file rather than macro file. | 267 | // This must be a normal source file rather than macro file. |
227 | let hir_path = | 268 | let hir_path = |
228 | crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; | 269 | crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; |
@@ -307,10 +348,21 @@ impl SourceAnalyzer { | |||
307 | db: &dyn HirDatabase, | 348 | db: &dyn HirDatabase, |
308 | macro_call: InFile<&ast::MacroCall>, | 349 | macro_call: InFile<&ast::MacroCall>, |
309 | ) -> Option<HirFileId> { | 350 | ) -> Option<HirFileId> { |
310 | let macro_call_id = macro_call.as_call_id(db.upcast(), |path| { | 351 | let krate = self.resolver.krate()?; |
352 | let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { | ||
311 | self.resolver.resolve_path_as_macro(db.upcast(), &path) | 353 | self.resolver.resolve_path_as_macro(db.upcast(), &path) |
312 | })?; | 354 | })?; |
313 | Some(macro_call_id.as_file()) | 355 | Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64) |
356 | } | ||
357 | |||
358 | pub(crate) fn resolve_variant( | ||
359 | &self, | ||
360 | db: &dyn HirDatabase, | ||
361 | record_lit: ast::RecordLit, | ||
362 | ) -> Option<VariantId> { | ||
363 | let infer = self.infer.as_ref()?; | ||
364 | let expr_id = self.expr_id(db, &record_lit.into())?; | ||
365 | infer.variant_resolution_for_expr(expr_id) | ||
314 | } | 366 | } |
315 | } | 367 | } |
316 | 368 | ||