aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model.rs125
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/has_source.rs10
-rw-r--r--crates/ra_hir/src/semantics.rs15
-rw-r--r--crates/ra_hir/src/source_analyzer.rs40
5 files changed, 181 insertions, 13 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 1a9f6cc76..a379b9f49 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -26,15 +26,12 @@ use hir_ty::{
26 autoderef, 26 autoderef,
27 display::{HirDisplayError, HirFormatter}, 27 display::{HirDisplayError, HirFormatter},
28 expr::ExprValidator, 28 expr::ExprValidator,
29 method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty, 29 method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
30 TyDefId, TypeCtor, 30 TraitEnvironment, Ty, TyDefId, TypeCtor,
31}; 31};
32use ra_db::{CrateId, CrateName, Edition, FileId}; 32use ra_db::{CrateId, CrateName, Edition, FileId};
33use ra_prof::profile; 33use ra_prof::profile;
34use ra_syntax::{ 34use ra_syntax::ast::{self, AttrsOwner, NameOwner};
35 ast::{self, AttrsOwner, NameOwner},
36 AstNode,
37};
38use rustc_hash::FxHashSet; 35use rustc_hash::FxHashSet;
39 36
40use crate::{ 37use crate::{
@@ -186,10 +183,27 @@ impl ModuleDef {
186 183
187 module.visibility_of(db, self) 184 module.visibility_of(db, self)
188 } 185 }
186
187 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
188 match self {
189 ModuleDef::Adt(it) => Some(it.name(db)),
190 ModuleDef::Trait(it) => Some(it.name(db)),
191 ModuleDef::Function(it) => Some(it.name(db)),
192 ModuleDef::EnumVariant(it) => Some(it.name(db)),
193 ModuleDef::TypeAlias(it) => Some(it.name(db)),
194
195 ModuleDef::Module(it) => it.name(db),
196 ModuleDef::Const(it) => it.name(db),
197 ModuleDef::Static(it) => it.name(db),
198
199 ModuleDef::BuiltinType(it) => Some(it.as_name()),
200 }
201 }
189} 202}
190 203
191pub use hir_def::{ 204pub use hir_def::{
192 attr::Attrs, item_scope::ItemInNs, visibility::Visibility, AssocItemId, AssocItemLoc, 205 attr::Attrs, item_scope::ItemInNs, item_tree::ItemTreeNode, visibility::Visibility,
206 AssocItemId, AssocItemLoc,
193}; 207};
194 208
195impl Module { 209impl Module {
@@ -856,7 +870,7 @@ where
856 ID: Lookup<Data = AssocItemLoc<AST>>, 870 ID: Lookup<Data = AssocItemLoc<AST>>,
857 DEF: From<ID>, 871 DEF: From<ID>,
858 CTOR: FnOnce(DEF) -> AssocItem, 872 CTOR: FnOnce(DEF) -> AssocItem,
859 AST: AstNode, 873 AST: ItemTreeNode,
860{ 874{
861 match id.lookup(db.upcast()).container { 875 match id.lookup(db.upcast()).container {
862 AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))), 876 AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
@@ -1359,6 +1373,27 @@ impl Type {
1359 Some(adt.into()) 1373 Some(adt.into())
1360 } 1374 }
1361 1375
1376 pub fn as_dyn_trait(&self) -> Option<Trait> {
1377 self.ty.value.dyn_trait().map(Into::into)
1378 }
1379
1380 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
1381 self.ty.value.impl_trait_bounds(db).map(|it| {
1382 it.into_iter()
1383 .filter_map(|pred| match pred {
1384 hir_ty::GenericPredicate::Implemented(trait_ref) => {
1385 Some(Trait::from(trait_ref.trait_))
1386 }
1387 _ => None,
1388 })
1389 .collect()
1390 })
1391 }
1392
1393 pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
1394 self.ty.value.associated_type_parent_trait(db).map(Into::into)
1395 }
1396
1362 // FIXME: provide required accessors such that it becomes implementable from outside. 1397 // FIXME: provide required accessors such that it becomes implementable from outside.
1363 pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { 1398 pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
1364 match (&self.ty.value, &other.ty.value) { 1399 match (&self.ty.value, &other.ty.value) {
@@ -1380,6 +1415,80 @@ impl Type {
1380 ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, 1415 ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
1381 } 1416 }
1382 } 1417 }
1418
1419 pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
1420 // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
1421 // We need a different order here.
1422
1423 fn walk_substs(
1424 db: &dyn HirDatabase,
1425 type_: &Type,
1426 substs: &Substs,
1427 cb: &mut impl FnMut(Type),
1428 ) {
1429 for ty in substs.iter() {
1430 walk_type(db, &type_.derived(ty.clone()), cb);
1431 }
1432 }
1433
1434 fn walk_bounds(
1435 db: &dyn HirDatabase,
1436 type_: &Type,
1437 bounds: &[GenericPredicate],
1438 cb: &mut impl FnMut(Type),
1439 ) {
1440 for pred in bounds {
1441 match pred {
1442 GenericPredicate::Implemented(trait_ref) => {
1443 cb(type_.clone());
1444 walk_substs(db, type_, &trait_ref.substs, cb);
1445 }
1446 _ => (),
1447 }
1448 }
1449 }
1450
1451 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
1452 let ty = type_.ty.value.strip_references();
1453 match ty {
1454 Ty::Apply(ApplicationTy { ctor, parameters }) => {
1455 match ctor {
1456 TypeCtor::Adt(_) => {
1457 cb(type_.derived(ty.clone()));
1458 }
1459 TypeCtor::AssociatedType(_) => {
1460 if let Some(_) = ty.associated_type_parent_trait(db) {
1461 cb(type_.derived(ty.clone()));
1462 }
1463 }
1464 _ => (),
1465 }
1466
1467 // adt params, tuples, etc...
1468 walk_substs(db, type_, parameters, cb);
1469 }
1470 Ty::Opaque(opaque_ty) => {
1471 if let Some(bounds) = ty.impl_trait_bounds(db) {
1472 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1473 }
1474
1475 walk_substs(db, type_, &opaque_ty.parameters, cb);
1476 }
1477 Ty::Placeholder(_) => {
1478 if let Some(bounds) = ty.impl_trait_bounds(db) {
1479 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1480 }
1481 }
1482 Ty::Dyn(bounds) => {
1483 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
1484 }
1485
1486 _ => (),
1487 }
1488 }
1489
1490 walk_type(db, self, &mut cb);
1491 }
1383} 1492}
1384 1493
1385impl HirDisplay for Type { 1494impl HirDisplay for Type {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index b6b665de1..bb67952de 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -6,7 +6,7 @@ pub use hir_def::db::{
6 ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, ImportMapQuery, 6 ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, ImportMapQuery,
7 InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, 7 InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery,
8 InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, 8 InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery,
9 InternUnionQuery, LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, StaticDataQuery, 9 InternUnionQuery, ItemTreeQuery, LangItemQuery, ModuleLangItemsQuery, StaticDataQuery,
10 StructDataQuery, TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, 10 StructDataQuery, TraitDataQuery, TypeAliasDataQuery, UnionDataQuery,
11}; 11};
12pub use hir_expand::db::{ 12pub use hir_expand::db::{
@@ -16,7 +16,7 @@ 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, ImplsFromDepsQuery,
20 ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, 20 ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery,
21 InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, 21 InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery,
22 TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery, 22 TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery,
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/semantics.rs b/crates/ra_hir/src/semantics.rs
index a232a5856..6a49c424a 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};
@@ -104,6 +104,13 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
104 tree 104 tree
105 } 105 }
106 106
107 pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST {
108 let file_id = d.source().file_id;
109 let root = self.db.parse_or_expand(file_id).unwrap();
110 self.cache(root, file_id);
111 d.ast(self.db)
112 }
113
107 pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { 114 pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
108 let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); 115 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); 116 let sa = self.analyze2(macro_call.map(|it| it.syntax()), None);
@@ -247,6 +254,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
247 self.analyze(path.syntax()).resolve_path(self.db, path) 254 self.analyze(path.syntax()).resolve_path(self.db, path)
248 } 255 }
249 256
257 pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> {
258 self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit)
259 }
260
250 pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { 261 pub fn lower_path(&self, path: &ast::Path) -> Option<Path> {
251 let src = self.find_file(path.syntax().clone()); 262 let src = self.find_file(path.syntax().clone());
252 Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) 263 Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into()))
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 7c6bbea13..1d6c47103 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -216,13 +216,43 @@ impl SourceAnalyzer {
216 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { 216 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
217 return Some(PathResolution::AssocItem(assoc.into())); 217 return Some(PathResolution::AssocItem(assoc.into()));
218 } 218 }
219 if let Some(VariantId::EnumVariantId(variant)) =
220 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
221 {
222 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
223 }
219 } 224 }
225
220 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { 226 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) {
221 let pat_id = self.pat_id(&path_pat.into())?; 227 let pat_id = self.pat_id(&path_pat.into())?;
222 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { 228 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
223 return Some(PathResolution::AssocItem(assoc.into())); 229 return Some(PathResolution::AssocItem(assoc.into()));
224 } 230 }
231 if let Some(VariantId::EnumVariantId(variant)) =
232 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
233 {
234 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
235 }
236 }
237
238 if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordLit::cast) {
239 let expr_id = self.expr_id(db, &rec_lit.into())?;
240 if let Some(VariantId::EnumVariantId(variant)) =
241 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
242 {
243 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
244 }
225 } 245 }
246
247 if let Some(rec_pat) = path.syntax().parent().and_then(ast::RecordPat::cast) {
248 let pat_id = self.pat_id(&rec_pat.into())?;
249 if let Some(VariantId::EnumVariantId(variant)) =
250 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
251 {
252 return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
253 }
254 }
255
226 // This must be a normal source file rather than macro file. 256 // This must be a normal source file rather than macro file.
227 let hir_path = 257 let hir_path =
228 crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; 258 crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?;
@@ -313,6 +343,16 @@ impl SourceAnalyzer {
313 })?; 343 })?;
314 Some(macro_call_id.as_file()) 344 Some(macro_call_id.as_file())
315 } 345 }
346
347 pub(crate) fn resolve_variant(
348 &self,
349 db: &dyn HirDatabase,
350 record_lit: ast::RecordLit,
351 ) -> Option<VariantId> {
352 let infer = self.infer.as_ref()?;
353 let expr_id = self.expr_id(db, &record_lit.into())?;
354 infer.variant_resolution_for_expr(expr_id)
355 }
316} 356}
317 357
318fn scope_for( 358fn scope_for(