aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/Cargo.toml2
-rw-r--r--crates/ra_hir/src/code_model.rs231
-rw-r--r--crates/ra_hir/src/db.rs18
-rw-r--r--crates/ra_hir/src/diagnostics.rs4
-rw-r--r--crates/ra_hir/src/has_source.rs10
-rw-r--r--crates/ra_hir/src/lib.rs21
-rw-r--r--crates/ra_hir/src/semantics.rs329
-rw-r--r--crates/ra_hir/src/semantics/source_to_def.rs12
-rw-r--r--crates/ra_hir/src/source_analyzer.rs60
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"
3name = "ra_hir" 3name = "ra_hir"
4version = "0.1.0" 4version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6license = "MIT OR Apache-2.0"
6 7
7[lib] 8[lib]
8doctest = false 9doctest = false
@@ -15,6 +16,7 @@ arrayvec = "0.5.1"
15 16
16itertools = "0.9.0" 17itertools = "0.9.0"
17 18
19stdx = { path = "../stdx" }
18ra_syntax = { path = "../ra_syntax" } 20ra_syntax = { path = "../ra_syntax" }
19ra_db = { path = "../ra_db" } 21ra_db = { path = "../ra_db" }
20ra_prof = { path = "../ra_prof" } 22ra_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::{
24use hir_ty::{ 25use 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};
31use ra_db::{CrateId, CrateName, Edition, FileId}; 31use ra_db::{CrateId, Edition, FileId};
32use ra_prof::profile; 32use ra_prof::profile;
33use ra_syntax::{ 33use ra_syntax::{
34 ast::{self, AttrsOwner, NameOwner}, 34 ast::{self, AttrsOwner, NameOwner},
35 AstNode, 35 AstNode,
36}; 36};
37use rustc_hash::FxHashSet; 37use rustc_hash::FxHashSet;
38use stdx::impl_from;
38 39
39use crate::{ 40use 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}
125impl_froms!( 143impl_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
137impl ModuleDef { 156impl 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
173pub use hir_def::{ 208pub 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
177impl Module { 213impl Module {
@@ -504,12 +540,12 @@ pub enum Adt {
504 Union(Union), 540 Union(Union),
505 Enum(Enum), 541 Enum(Enum),
506} 542}
507impl_froms!(Adt: Struct, Union, Enum); 543impl_from!(Struct, Union, Enum for Adt);
508 544
509impl Adt { 545impl 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}
550impl_froms!(VariantDef: Struct, Union, EnumVariant); 586impl_from!(Struct, Union, EnumVariant for VariantDef);
551 587
552impl VariantDef { 588impl 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 629impl_from!(Function, Const, Static for DefWithBody);
594impl_froms!(DefWithBody: Function, Const, Static);
595 630
596impl DefWithBody { 631impl 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 {
735impl TypeAlias { 770impl 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}
890impl_froms!( 925impl_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
900impl GenericDef { 936impl GenericDef {
@@ -915,6 +951,16 @@ pub struct Local {
915} 951}
916 952
917impl Local { 953impl 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
1011impl ImplDef { 1060impl 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
1359impl HirDisplay for Type { 1509impl HirDisplay for Type {
@@ -1421,8 +1571,8 @@ pub enum AttrDef {
1421 MacroDef(MacroDef), 1571 MacroDef(MacroDef),
1422} 1572}
1423 1573
1424impl_froms!( 1574impl_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
1437pub trait HasAttrs { 1588pub 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 @@
3pub use hir_def::db::{ 3pub 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};
12pub use hir_expand::db::{ 12pub 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::{
16pub use hir_ty::db::{ 16pub 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
2pub use hir_def::diagnostics::UnresolvedModule; 2pub use hir_def::diagnostics::UnresolvedModule;
3pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; 3pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
4pub use hir_ty::diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField}; 4pub 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
3use either::Either; 3use either::Either;
4use hir_def::{ 4use 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
22macro_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
41mod semantics; 22mod semantics;
42pub mod db; 23pub mod db;
43mod source_analyzer; 24mod 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};
77pub use hir_ty::{display::HirDisplay, CallableDef}; 58pub 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
7use hir_def::{ 7use hir_def::{
8 resolver::{self, HasResolver, Resolver}, 8 resolver::{self, HasResolver, Resolver},
9 AsMacroCall, TraitId, 9 AsMacroCall, TraitId, VariantId,
10}; 10};
11use hir_expand::{hygiene::Hygiene, ExpansionInfo}; 11use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo};
12use hir_ty::associated_type_shorthand_candidates; 12use hir_ty::associated_type_shorthand_candidates;
13use itertools::Itertools; 13use itertools::Itertools;
14use ra_db::{FileId, FileRange}; 14use 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};
30use resolver::TypeNs; 30use 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.
84pub struct Semantics<'db, DB> { 84pub struct Semantics<'db, DB> {
85 pub db: &'db DB, 85 pub db: &'db DB,
86 imp: SemanticsImpl<'db>,
87}
88
89pub 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
96impl<'db, DB: HirDatabase> Semantics<'db, DB> { 101impl<'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
272impl<'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(&macro_call))?; 324 let file_id = sa.expand(self.db, token.with_value(&macro_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, &param)
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> {
370pub trait ToDef: AstNode + Clone { 532pub 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
376macro_rules! to_def_impls { 538macro_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
410pub struct SemanticsScope<'a, DB> { 572#[derive(Debug)]
411 pub db: &'a DB, 573pub struct SemanticsScope<'a> {
574 pub db: &'a dyn HirDatabase,
412 resolver: Resolver, 575 resolver: Resolver,
413} 576}
414 577
415impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> { 578impl<'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};
18use rustc_hash::FxHashMap; 18use rustc_hash::FxHashMap;
19use stdx::impl_from;
19 20
20use crate::{db::HirDatabase, InFile, MacroDefId}; 21use 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}
253impl_froms! { 259impl_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
264impl ChildContainer { 271impl 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};
19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
20use hir_ty::{ 20use 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};
24use ra_syntax::{ 24use 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