aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_db/src/lib.rs14
-rw-r--r--crates/ra_hir/src/code_model.rs13
-rw-r--r--crates/ra_hir/src/code_model/src.rs5
-rw-r--r--crates/ra_hir/src/db.rs10
-rw-r--r--crates/ra_hir/src/debug.rs3
-rw-r--r--crates/ra_hir/src/diagnostics.rs3
-rw-r--r--crates/ra_hir/src/from_source.rs22
-rw-r--r--crates/ra_hir/src/ids.rs45
-rw-r--r--crates/ra_hir/src/lib.rs6
-rw-r--r--crates/ra_hir/src/source_binder.rs17
-rw-r--r--crates/ra_hir/src/ty.rs8
-rw-r--r--crates/ra_hir/src/ty/tests.rs2
-rw-r--r--crates/ra_hir/src/ty/traits.rs11
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs18
-rw-r--r--crates/ra_hir_def/src/attr.rs108
-rw-r--r--crates/ra_hir_def/src/body.rs3
-rw-r--r--crates/ra_hir_def/src/data.rs2
-rw-r--r--crates/ra_hir_def/src/db.rs5
-rw-r--r--crates/ra_hir_def/src/docs.rs2
-rw-r--r--crates/ra_hir_def/src/lang_item.rs4
-rw-r--r--crates/ra_hir_def/src/lib.rs67
-rw-r--r--crates/ra_hir_def/src/nameres.rs35
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs61
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs7
-rw-r--r--crates/ra_hir_def/src/resolver.rs2
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs2
26 files changed, 232 insertions, 243 deletions
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index f9d012cb0..e8852531b 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -15,6 +15,20 @@ pub use crate::{
15pub use relative_path::{RelativePath, RelativePathBuf}; 15pub use relative_path::{RelativePath, RelativePathBuf};
16pub use salsa; 16pub use salsa;
17 17
18#[macro_export]
19macro_rules! impl_intern_key {
20 ($name:ident) => {
21 impl $crate::salsa::InternKey for $name {
22 fn from_intern_id(v: $crate::salsa::InternId) -> Self {
23 $name(v)
24 }
25 fn as_intern_id(&self) -> $crate::salsa::InternId {
26 self.0
27 }
28 }
29 };
30}
31
18pub trait CheckCanceled { 32pub trait CheckCanceled {
19 /// Aborts current query if there are pending changes. 33 /// Aborts current query if there are pending changes.
20 /// 34 ///
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index fd7776fb7..905bb5bcb 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -12,13 +12,14 @@ use hir_def::{
12 per_ns::PerNs, 12 per_ns::PerNs,
13 resolver::{HasResolver, TypeNs}, 13 resolver::{HasResolver, TypeNs},
14 type_ref::TypeRef, 14 type_ref::TypeRef,
15 ContainerId, HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, 15 AstItemDef, ConstId, ContainerId, EnumId, FunctionId, HasModule, ImplId, LocalEnumVariantId,
16 LocalStructFieldId, Lookup, ModuleId, UnionId, 16 LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId,
17 TraitId, TypeAliasId, UnionId,
17}; 18};
18use hir_expand::{ 19use hir_expand::{
19 diagnostics::DiagnosticSink, 20 diagnostics::DiagnosticSink,
20 name::{self, AsName}, 21 name::{self, AsName},
21 AstId, 22 AstId, MacroDefId,
22}; 23};
23use ra_db::{CrateId, Edition, FileId, FilePosition}; 24use ra_db::{CrateId, Edition, FileId, FilePosition};
24use ra_syntax::{ast, AstNode, SyntaxNode}; 25use ra_syntax::{ast, AstNode, SyntaxNode};
@@ -26,10 +27,6 @@ use ra_syntax::{ast, AstNode, SyntaxNode};
26use crate::{ 27use crate::{
27 db::{DefDatabase, HirDatabase}, 28 db::{DefDatabase, HirDatabase},
28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, 29 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
29 ids::{
30 AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId,
31 TypeAliasId,
32 },
33 ty::{InferenceResult, Namespace, TraitRef}, 30 ty::{InferenceResult, Namespace, TraitRef},
34 Either, HasSource, Name, Source, Ty, 31 Either, HasSource, Name, Source, Ty,
35}; 32};
@@ -737,7 +734,7 @@ pub struct Static {
737 734
738impl Static { 735impl Static {
739 pub fn module(self, db: &impl DefDatabase) -> Module { 736 pub fn module(self, db: &impl DefDatabase) -> Module {
740 Module { id: self.id.module(db) } 737 Module { id: self.id.lookup(db).module(db) }
741 } 738 }
742 739
743 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 740 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index b7bafe23d..b9d21bdd7 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -1,12 +1,11 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{HasChildSource, HasSource as _, Lookup, VariantId}; 3use hir_def::{AstItemDef, HasChildSource, HasSource as _, Lookup, VariantId};
4use hir_expand::either::Either; 4use hir_expand::either::Either;
5use ra_syntax::ast::{self, AstNode}; 5use ra_syntax::ast::{self, AstNode};
6 6
7use crate::{ 7use crate::{
8 db::{DefDatabase, HirDatabase}, 8 db::{DefDatabase, HirDatabase},
9 ids::AstItemDef,
10 Const, Enum, EnumVariant, FieldSource, Function, HasBody, Import, MacroDef, Module, 9 Const, Enum, EnumVariant, FieldSource, Function, HasBody, Import, MacroDef, Module,
11 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, 10 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
12}; 11};
@@ -89,7 +88,7 @@ impl HasSource for Const {
89impl HasSource for Static { 88impl HasSource for Static {
90 type Ast = ast::StaticDef; 89 type Ast = ast::StaticDef;
91 fn source(self, db: &impl DefDatabase) -> Source<ast::StaticDef> { 90 fn source(self, db: &impl DefDatabase) -> Source<ast::StaticDef> {
92 self.id.source(db) 91 self.id.lookup(db).source(db)
93 } 92 }
94} 93}
95impl HasSource for Trait { 94impl HasSource for Trait {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 3ae5df8d5..a9dab2d25 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -5,7 +5,6 @@ use std::sync::Arc;
5use ra_db::salsa; 5use ra_db::salsa;
6 6
7use crate::{ 7use crate::{
8 ids,
9 ty::{ 8 ty::{
10 method_resolution::CrateImplBlocks, 9 method_resolution::CrateImplBlocks,
11 traits::{AssocTyValue, Impl}, 10 traits::{AssocTyValue, Impl},
@@ -71,11 +70,14 @@ pub trait HirDatabase: DefDatabase {
71 70
72 // Interned IDs for Chalk integration 71 // Interned IDs for Chalk integration
73 #[salsa::interned] 72 #[salsa::interned]
74 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId; 73 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::ty::TypeCtorId;
75 #[salsa::interned] 74 #[salsa::interned]
76 fn intern_chalk_impl(&self, impl_: Impl) -> ids::GlobalImplId; 75 fn intern_chalk_impl(&self, impl_: Impl) -> crate::ty::traits::GlobalImplId;
77 #[salsa::interned] 76 #[salsa::interned]
78 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> ids::AssocTyValueId; 77 fn intern_assoc_ty_value(
78 &self,
79 assoc_ty_value: AssocTyValue,
80 ) -> crate::ty::traits::AssocTyValueId;
79 81
80 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)] 82 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
81 fn associated_ty_data( 83 fn associated_ty_data(
diff --git a/crates/ra_hir/src/debug.rs b/crates/ra_hir/src/debug.rs
index 8ec371f6e..7a2810f71 100644
--- a/crates/ra_hir/src/debug.rs
+++ b/crates/ra_hir/src/debug.rs
@@ -22,9 +22,10 @@
22 22
23use std::fmt; 23use std::fmt;
24 24
25use hir_expand::HirFileId;
25use ra_db::{CrateId, FileId}; 26use ra_db::{CrateId, FileId};
26 27
27use crate::{db::HirDatabase, Crate, HirFileId, Module, Name}; 28use crate::{db::HirDatabase, Crate, Module, Name};
28 29
29impl Crate { 30impl Crate {
30 pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ { 31 pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index 7d1b64858..dafacba70 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -2,9 +2,10 @@
2 2
3use std::any::Any; 3use std::any::Any;
4 4
5use hir_expand::HirFileId;
5use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; 6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
6 7
7use crate::{db::AstDatabase, HirFileId, Name, Source}; 8use crate::{db::AstDatabase, Name, Source};
8 9
9pub use hir_def::diagnostics::UnresolvedModule; 10pub use hir_def::diagnostics::UnresolvedModule;
10pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; 11pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index b86307c58..f506bba70 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId}; 3use hir_def::{AstItemDef, LocationCtx, ModuleId, StructId, StructOrUnionId, UnionId};
4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
5use ra_syntax::{ 5use ra_syntax::{
6 ast::{self, AstNode, NameOwner}, 6 ast::{self, AstNode, NameOwner},
@@ -9,7 +9,6 @@ use ra_syntax::{
9 9
10use crate::{ 10use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 11 db::{AstDatabase, DefDatabase, HirDatabase},
12 ids::{AstItemDef, LocationCtx},
13 AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, 12 AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource,
14 ImplBlock, Local, MacroDef, Module, ModuleDef, ModuleSource, Source, Static, Struct, 13 ImplBlock, Local, MacroDef, Module, ModuleDef, ModuleSource, Source, Static, Struct,
15 StructField, Trait, TypeAlias, Union, VariantDef, 14 StructField, Trait, TypeAlias, Union, VariantDef,
@@ -105,10 +104,21 @@ impl FromSource for Const {
105impl FromSource for Static { 104impl FromSource for Static {
106 type Ast = ast::StaticDef; 105 type Ast = ast::StaticDef;
107 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 106 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
108 let id = from_source(db, src)?; 107 let module = match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
109 Some(Static { id }) 108 Container::Module(it) => it,
109 Container::Trait(_) | Container::ImplBlock(_) => return None,
110 };
111 module
112 .declarations(db)
113 .into_iter()
114 .filter_map(|it| match it {
115 ModuleDef::Static(it) => Some(it),
116 _ => None,
117 })
118 .find(|it| same_source(&it.source(db), &src))
110 } 119 }
111} 120}
121
112impl FromSource for TypeAlias { 122impl FromSource for TypeAlias {
113 type Ast = ast::TypeAliasDef; 123 type Ast = ast::TypeAliasDef;
114 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 124 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
@@ -272,7 +282,9 @@ where
272 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); 282 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
273 let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; 283 let module = Module::from_definition(db, Source::new(src.file_id, module_src))?;
274 let ctx = LocationCtx::new(db, module.id, src.file_id); 284 let ctx = LocationCtx::new(db, module.id, src.file_id);
275 Some(DEF::from_ast(ctx, &src.value)) 285 let items = db.ast_id_map(src.file_id);
286 let item_id = items.ast_id(&src.value);
287 Some(DEF::from_ast_id(ctx, item_id))
276} 288}
277 289
278enum Container { 290enum Container {
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
deleted file mode 100644
index 2b59365fb..000000000
--- a/crates/ra_hir/src/ids.rs
+++ /dev/null
@@ -1,45 +0,0 @@
1//! hir makes heavy use of ids: integer (u32) handlers to various things. You
2//! can think of id as a pointer (but without a lifetime) or a file descriptor
3//! (but for hir objects).
4//!
5//! This module defines a bunch of ids we are using. The most important ones are
6//! probably `HirFileId` and `DefId`.
7
8use ra_db::salsa;
9
10pub use hir_def::{
11 AstItemDef, ConstId, EnumId, FunctionId, ItemLoc, LocationCtx, StaticId, StructId, TraitId,
12 TypeAliasId,
13};
14pub use hir_expand::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, MacroFileKind};
15
16macro_rules! impl_intern_key {
17 ($name:ident) => {
18 impl salsa::InternKey for $name {
19 fn from_intern_id(v: salsa::InternId) -> Self {
20 $name(v)
21 }
22 fn as_intern_id(&self) -> salsa::InternId {
23 self.0
24 }
25 }
26 };
27}
28
29/// This exists just for Chalk, because Chalk just has a single `StructId` where
30/// we have different kinds of ADTs, primitive types and special type
31/// constructors like tuples and function pointers.
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub struct TypeCtorId(salsa::InternId);
34impl_intern_key!(TypeCtorId);
35
36/// This exists just for Chalk, because our ImplIds are only unique per module.
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
38pub struct GlobalImplId(salsa::InternId);
39impl_intern_key!(GlobalImplId);
40
41/// This exists just for Chalk, because it needs a unique ID for each associated
42/// type value in an impl (even synthetic ones).
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
44pub struct AssocTyValueId(salsa::InternId);
45impl_intern_key!(AssocTyValueId);
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index e51d4d063..8c589c728 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -31,7 +31,6 @@ pub mod debug;
31pub mod db; 31pub mod db;
32pub mod source_binder; 32pub mod source_binder;
33 33
34mod ids;
35mod ty; 34mod ty;
36mod impl_block; 35mod impl_block;
37mod expr; 36mod expr;
@@ -58,7 +57,6 @@ pub use crate::{
58 }, 57 },
59 expr::ExprScopes, 58 expr::ExprScopes,
60 from_source::FromSource, 59 from_source::FromSource,
61 ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile},
62 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 60 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
63 ty::{ 61 ty::{
64 display::HirDisplay, 62 display::HirDisplay,
@@ -73,4 +71,6 @@ pub use hir_def::{
73 path::{Path, PathKind}, 71 path::{Path, PathKind},
74 type_ref::Mutability, 72 type_ref::Mutability,
75}; 73};
76pub use hir_expand::{either::Either, name::Name, Source}; 74pub use hir_expand::{
75 either::Either, name::Name, HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Source,
76};
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 797f90d50..cfc4bd326 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -13,7 +13,9 @@ use hir_def::{
13 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, 13 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
14 DefWithBodyId, 14 DefWithBodyId,
15}; 15};
16use hir_expand::{name::AsName, AstId, MacroCallId, MacroCallLoc, MacroFileKind, Source}; 16use hir_expand::{
17 name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind, Source,
18};
17use ra_syntax::{ 19use ra_syntax::{
18 ast::{self, AstNode}, 20 ast::{self, AstNode},
19 match_ast, AstPtr, 21 match_ast, AstPtr,
@@ -24,11 +26,10 @@ use ra_syntax::{
24use crate::{ 26use crate::{
25 db::HirDatabase, 27 db::HirDatabase,
26 expr::{BodySourceMap, ExprScopes, ScopeId}, 28 expr::{BodySourceMap, ExprScopes, ScopeId},
27 ids::LocationCtx,
28 ty::method_resolution::{self, implements_trait}, 29 ty::method_resolution::{self, implements_trait},
29 Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, 30 Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function,
30 GenericParam, HasBody, HirFileId, Local, MacroDef, Module, Name, Path, ScopeDef, Static, 31 GenericParam, HasBody, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty,
31 Struct, Trait, Ty, TypeAlias, 32 TypeAlias,
32}; 33};
33 34
34fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { 35fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> {
@@ -67,16 +68,12 @@ fn def_with_body_from_child_node(
67 db: &impl HirDatabase, 68 db: &impl HirDatabase,
68 child: Source<&SyntaxNode>, 69 child: Source<&SyntaxNode>,
69) -> Option<DefWithBody> { 70) -> Option<DefWithBody> {
70 let module_source = crate::ModuleSource::from_child_node(db, child);
71 let module = Module::from_definition(db, Source::new(child.file_id, module_source))?;
72 let ctx = LocationCtx::new(db, module.id, child.file_id);
73
74 child.value.ancestors().find_map(|node| { 71 child.value.ancestors().find_map(|node| {
75 match_ast! { 72 match_ast! {
76 match node { 73 match node {
77 ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); }, 74 ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); },
78 ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); }, 75 ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); },
79 ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) }, 76 ast::StaticDef(def) => { return Static::from_source(db, child.with_value(def)).map(DefWithBody::from); },
80 _ => { None }, 77 _ => { None },
81 } 78 }
82 } 79 }
@@ -544,7 +541,7 @@ fn adjust(
544} 541}
545 542
546/// Given a `ast::MacroCall`, return what `MacroKindFile` it belongs to. 543/// Given a `ast::MacroCall`, return what `MacroKindFile` it belongs to.
547/// FIXME: Not completed 544/// FIXME: Not completed
548fn to_macro_file_kind(macro_call: &ast::MacroCall) -> MacroFileKind { 545fn to_macro_file_kind(macro_call: &ast::MacroCall) -> MacroFileKind {
549 let syn = macro_call.syntax(); 546 let syn = macro_call.syntax();
550 let parent = match syn.parent() { 547 let parent = match syn.parent() {
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 95b8df181..309bd2727 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -18,6 +18,7 @@ use std::sync::Arc;
18use std::{fmt, iter, mem}; 18use std::{fmt, iter, mem};
19 19
20use hir_def::{generics::GenericParams, AdtId}; 20use hir_def::{generics::GenericParams, AdtId};
21use ra_db::{impl_intern_key, salsa};
21 22
22use crate::{ 23use crate::{
23 db::HirDatabase, expr::ExprId, util::make_mut_slice, Adt, Crate, DefWithBody, FloatTy, 24 db::HirDatabase, expr::ExprId, util::make_mut_slice, Adt, Crate, DefWithBody, FloatTy,
@@ -114,6 +115,13 @@ pub enum TypeCtor {
114 Closure { def: DefWithBody, expr: ExprId }, 115 Closure { def: DefWithBody, expr: ExprId },
115} 116}
116 117
118/// This exists just for Chalk, because Chalk just has a single `StructId` where
119/// we have different kinds of ADTs, primitive types and special type
120/// constructors like tuples and function pointers.
121#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
122pub struct TypeCtorId(salsa::InternId);
123impl_intern_key!(TypeCtorId);
124
117impl TypeCtor { 125impl TypeCtor {
118 pub fn num_ty_params(self, db: &impl HirDatabase) -> usize { 126 pub fn num_ty_params(self, db: &impl HirDatabase) -> usize {
119 match self { 127 match self {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 17a50cf74..3209c66bd 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2550,8 +2550,6 @@ fn test() {
2550 [233; 246) 'GLOBAL_STATIC': u32 2550 [233; 246) 'GLOBAL_STATIC': u32
2551 [256; 257) 'w': u32 2551 [256; 257) 'w': u32
2552 [260; 277) 'GLOBAL...IC_MUT': u32 2552 [260; 277) 'GLOBAL...IC_MUT': u32
2553 [118; 120) '99': u32
2554 [161; 163) '99': u32
2555 "### 2553 "###
2556 ); 2554 );
2557} 2555}
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 45f725438..268fa09e4 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex};
3 3
4use chalk_ir::{cast::Cast, family::ChalkIr}; 4use chalk_ir::{cast::Cast, family::ChalkIr};
5use log::debug; 5use log::debug;
6use ra_db::salsa; 6use ra_db::{impl_intern_key, salsa};
7use ra_prof::profile; 7use ra_prof::profile;
8use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
9 9
@@ -304,6 +304,10 @@ pub enum Impl {
304 /// Closure types implement the Fn traits synthetically. 304 /// Closure types implement the Fn traits synthetically.
305 ClosureFnTraitImpl(ClosureFnTraitImplData), 305 ClosureFnTraitImpl(ClosureFnTraitImplData),
306} 306}
307/// This exists just for Chalk, because our ImplIds are only unique per module.
308#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
309pub struct GlobalImplId(salsa::InternId);
310impl_intern_key!(GlobalImplId);
307 311
308/// An associated type value. Usually this comes from a `type` declaration 312/// An associated type value. Usually this comes from a `type` declaration
309/// inside an impl block, but for built-in impls we have to synthesize it. 313/// inside an impl block, but for built-in impls we have to synthesize it.
@@ -315,3 +319,8 @@ pub enum AssocTyValue {
315 /// The output type of the Fn trait implementation. 319 /// The output type of the Fn trait implementation.
316 ClosureFnTraitImplOutput(ClosureFnTraitImplData), 320 ClosureFnTraitImplOutput(ClosureFnTraitImplData),
317} 321}
322/// This exists just for Chalk, because it needs a unique ID for each associated
323/// type value in an impl (even synthetic ones).
324#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
325pub struct AssocTyValueId(salsa::InternId);
326impl_intern_key!(AssocTyValueId);
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 53818a5e5..9efdc53c4 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -847,38 +847,38 @@ fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId {
847 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } 847 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() }
848} 848}
849 849
850impl From<chalk_ir::StructId> for crate::ids::TypeCtorId { 850impl From<chalk_ir::StructId> for crate::ty::TypeCtorId {
851 fn from(struct_id: chalk_ir::StructId) -> Self { 851 fn from(struct_id: chalk_ir::StructId) -> Self {
852 id_from_chalk(struct_id.0) 852 id_from_chalk(struct_id.0)
853 } 853 }
854} 854}
855 855
856impl From<crate::ids::TypeCtorId> for chalk_ir::StructId { 856impl From<crate::ty::TypeCtorId> for chalk_ir::StructId {
857 fn from(type_ctor_id: crate::ids::TypeCtorId) -> Self { 857 fn from(type_ctor_id: crate::ty::TypeCtorId) -> Self {
858 chalk_ir::StructId(id_to_chalk(type_ctor_id)) 858 chalk_ir::StructId(id_to_chalk(type_ctor_id))
859 } 859 }
860} 860}
861 861
862impl From<chalk_ir::ImplId> for crate::ids::GlobalImplId { 862impl From<chalk_ir::ImplId> for crate::ty::traits::GlobalImplId {
863 fn from(impl_id: chalk_ir::ImplId) -> Self { 863 fn from(impl_id: chalk_ir::ImplId) -> Self {
864 id_from_chalk(impl_id.0) 864 id_from_chalk(impl_id.0)
865 } 865 }
866} 866}
867 867
868impl From<crate::ids::GlobalImplId> for chalk_ir::ImplId { 868impl From<crate::ty::traits::GlobalImplId> for chalk_ir::ImplId {
869 fn from(impl_id: crate::ids::GlobalImplId) -> Self { 869 fn from(impl_id: crate::ty::traits::GlobalImplId) -> Self {
870 chalk_ir::ImplId(id_to_chalk(impl_id)) 870 chalk_ir::ImplId(id_to_chalk(impl_id))
871 } 871 }
872} 872}
873 873
874impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ids::AssocTyValueId { 874impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ty::traits::AssocTyValueId {
875 fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { 875 fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self {
876 id_from_chalk(id.0) 876 id_from_chalk(id.0)
877 } 877 }
878} 878}
879 879
880impl From<crate::ids::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { 880impl From<crate::ty::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId {
881 fn from(assoc_ty_value_id: crate::ids::AssocTyValueId) -> Self { 881 fn from(assoc_ty_value_id: crate::ty::traits::AssocTyValueId) -> Self {
882 chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) 882 chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id))
883 } 883 }
884} 884}
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 48ce8cd93..53456fc08 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -2,9 +2,8 @@
2 2
3use std::{ops, sync::Arc}; 3use std::{ops, sync::Arc};
4 4
5use hir_expand::{either::Either, hygiene::Hygiene, AstId}; 5use hir_expand::{either::Either, hygiene::Hygiene, AstId, Source};
6use mbe::ast_to_token_tree; 6use mbe::ast_to_token_tree;
7use ra_cfg::CfgOptions;
8use ra_syntax::{ 7use ra_syntax::{
9 ast::{self, AstNode, AttrsOwner}, 8 ast::{self, AstNode, AttrsOwner},
10 SmolStr, 9 SmolStr,
@@ -40,50 +39,53 @@ impl Attrs {
40 Some(it) => it, 39 Some(it) => it,
41 None => return Attrs::default(), 40 None => return Attrs::default(),
42 }; 41 };
43 let hygiene = Hygiene::new(db, src.file_id); 42 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
44 Attr::from_attrs_owner(&src.value, &hygiene)
45 } 43 }
46 AttrDefId::StructFieldId(it) => { 44 AttrDefId::StructFieldId(it) => {
47 let src = it.parent.child_source(db); 45 let src = it.parent.child_source(db);
48 match &src.value[it.local_id] { 46 match &src.value[it.local_id] {
49 Either::A(_tuple) => Attrs::default(), 47 Either::A(_tuple) => Attrs::default(),
50 Either::B(record) => { 48 Either::B(record) => Attrs::from_attrs_owner(db, src.with_value(record)),
51 let hygiene = Hygiene::new(db, src.file_id);
52 Attr::from_attrs_owner(record, &hygiene)
53 }
54 } 49 }
55 } 50 }
56 AttrDefId::EnumVariantId(it) => { 51 AttrDefId::EnumVariantId(var_id) => {
57 let src = it.parent.child_source(db); 52 let src = var_id.parent.child_source(db);
58 let hygiene = Hygiene::new(db, src.file_id); 53 let src = src.as_ref().map(|it| &it[var_id.local_id]);
59 Attr::from_attrs_owner(&src.value[it.local_id], &hygiene) 54 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
60 } 55 }
61 AttrDefId::AdtId(it) => match it { 56 AttrDefId::AdtId(it) => match it {
62 AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), 57 AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
63 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 58 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
64 AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), 59 AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
65 }, 60 },
66 AttrDefId::StaticId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
67 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 61 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
68 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db), 62 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db),
69 AttrDefId::ImplId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 63 AttrDefId::ImplId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
70 AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db), 64 AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db),
65 AttrDefId::StaticId(it) => attrs_from_loc(it.lookup(db), db),
71 AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db), 66 AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db),
72 AttrDefId::TypeAliasId(it) => attrs_from_loc(it.lookup(db), db), 67 AttrDefId::TypeAliasId(it) => attrs_from_loc(it.lookup(db), db),
73 } 68 }
74 } 69 }
75 70
76 pub fn has_atom(&self, atom: &str) -> bool { 71 fn from_attrs_owner(db: &impl DefDatabase, owner: Source<&dyn AttrsOwner>) -> Attrs {
77 self.iter().any(|it| it.is_simple_atom(atom)) 72 let hygiene = Hygiene::new(db, owner.file_id);
73 Attrs::new(owner.value, &hygiene)
78 } 74 }
79 75
80 pub fn find_string_value(&self, key: &str) -> Option<SmolStr> { 76 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
81 self.iter().filter(|attr| attr.is_simple_atom(key)).find_map(|attr| { 77 let mut attrs = owner.attrs().peekable();
82 match attr.input.as_ref()? { 78 let entries = if attrs.peek().is_none() {
83 AttrInput::Literal(it) => Some(it.clone()), 79 // Avoid heap allocation
84 _ => None, 80 None
85 } 81 } else {
86 }) 82 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
83 };
84 Attrs { entries }
85 }
86
87 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
88 AttrQuery { attrs: self, key }
87 } 89 }
88} 90}
89 91
@@ -100,7 +102,7 @@ pub enum AttrInput {
100} 102}
101 103
102impl Attr { 104impl Attr {
103 pub(crate) fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> { 105 fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> {
104 let path = Path::from_src(ast.path()?, hygiene)?; 106 let path = Path::from_src(ast.path()?, hygiene)?;
105 let input = match ast.input() { 107 let input = match ast.input() {
106 None => None, 108 None => None,
@@ -116,46 +118,37 @@ impl Attr {
116 118
117 Some(Attr { path, input }) 119 Some(Attr { path, input })
118 } 120 }
121}
119 122
120 pub fn from_attrs_owner(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs { 123pub struct AttrQuery<'a> {
121 let mut attrs = owner.attrs().peekable(); 124 attrs: &'a Attrs,
122 let entries = if attrs.peek().is_none() { 125 key: &'static str,
123 // Avoid heap allocation 126}
124 None
125 } else {
126 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
127 };
128 Attrs { entries }
129 }
130 127
131 pub fn is_simple_atom(&self, name: &str) -> bool { 128impl<'a> AttrQuery<'a> {
132 // FIXME: Avoid cloning 129 pub fn tt_values(self) -> impl Iterator<Item = &'a Subtree> {
133 self.path.as_ident().map_or(false, |s| s.to_string() == name) 130 self.attrs().filter_map(|attr| match attr.input.as_ref()? {
131 AttrInput::TokenTree(it) => Some(it),
132 _ => None,
133 })
134 } 134 }
135 135
136 // FIXME: handle cfg_attr :-) 136 pub fn string_value(self) -> Option<&'a SmolStr> {
137 pub fn as_cfg(&self) -> Option<&Subtree> { 137 self.attrs().find_map(|attr| match attr.input.as_ref()? {
138 if !self.is_simple_atom("cfg") { 138 AttrInput::Literal(it) => Some(it),
139 return None;
140 }
141 match &self.input {
142 Some(AttrInput::TokenTree(subtree)) => Some(subtree),
143 _ => None, 139 _ => None,
144 } 140 })
145 } 141 }
146 142
147 pub fn as_path(&self) -> Option<&SmolStr> { 143 pub fn exists(self) -> bool {
148 if !self.is_simple_atom("path") { 144 self.attrs().next().is_some()
149 return None;
150 }
151 match &self.input {
152 Some(AttrInput::Literal(it)) => Some(it),
153 _ => None,
154 }
155 } 145 }
156 146
157 pub fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Option<bool> { 147 fn attrs(self) -> impl Iterator<Item = &'a Attr> {
158 cfg_options.is_cfg_enabled(self.as_cfg()?) 148 let key = self.key;
149 self.attrs
150 .iter()
151 .filter(move |attr| attr.path.as_ident().map_or(false, |s| s.to_string() == key))
159 } 152 }
160} 153}
161 154
@@ -164,8 +157,8 @@ where
164 N: ast::AttrsOwner, 157 N: ast::AttrsOwner,
165 D: DefDatabase, 158 D: DefDatabase,
166{ 159{
167 let hygiene = Hygiene::new(db, src.file_id()); 160 let src = Source::new(src.file_id(), src.to_node(db));
168 Attr::from_attrs_owner(&src.to_node(db), &hygiene) 161 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
169} 162}
170 163
171fn attrs_from_loc<T, D>(node: T, db: &D) -> Attrs 164fn attrs_from_loc<T, D>(node: T, db: &D) -> Attrs
@@ -175,6 +168,5 @@ where
175 D: DefDatabase, 168 D: DefDatabase,
176{ 169{
177 let src = node.source(db); 170 let src = node.source(db);
178 let hygiene = Hygiene::new(db, src.file_id); 171 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
179 Attr::from_attrs_owner(&src.value, &hygiene)
180} 172}
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 225638b42..1589085b5 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -17,7 +17,7 @@ use crate::{
17 expr::{Expr, ExprId, Pat, PatId}, 17 expr::{Expr, ExprId, Pat, PatId},
18 nameres::CrateDefMap, 18 nameres::CrateDefMap,
19 path::Path, 19 path::Path,
20 AstItemDef, DefWithBodyId, HasModule, HasSource, Lookup, ModuleId, 20 DefWithBodyId, HasModule, HasSource, Lookup, ModuleId,
21}; 21};
22 22
23pub struct Expander { 23pub struct Expander {
@@ -160,6 +160,7 @@ impl Body {
160 (src.file_id, c.module(db), src.value.body()) 160 (src.file_id, c.module(db), src.value.body())
161 } 161 }
162 DefWithBodyId::StaticId(s) => { 162 DefWithBodyId::StaticId(s) => {
163 let s = s.lookup(db);
163 let src = s.source(db); 164 let src = s.source(db);
164 (src.file_id, s.module(db), src.value.body()) 165 (src.file_id, s.module(db), src.value.body())
165 } 166 }
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index f0b3e198a..81a8ec18d 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -204,7 +204,7 @@ impl ConstData {
204 } 204 }
205 205
206 pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> { 206 pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> {
207 let node = konst.source(db).value; 207 let node = konst.lookup(db).source(db).value;
208 const_data_for(&node) 208 const_data_for(&node)
209 } 209 }
210} 210}
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 7fec2e8c0..32adb11bd 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -18,7 +18,8 @@ use crate::{
18 CrateDefMap, 18 CrateDefMap,
19 }, 19 },
20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId, 20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId,
21 ImplId, ItemLoc, ModuleId, StaticId, StructOrUnionId, TraitId, TypeAliasId, TypeAliasLoc, 21 ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructOrUnionId, TraitId, TypeAliasId,
22 TypeAliasLoc,
22}; 23};
23 24
24#[salsa::query_group(InternDatabaseStorage)] 25#[salsa::query_group(InternDatabaseStorage)]
@@ -32,7 +33,7 @@ pub trait InternDatabase: SourceDatabase {
32 #[salsa::interned] 33 #[salsa::interned]
33 fn intern_const(&self, loc: ConstLoc) -> ConstId; 34 fn intern_const(&self, loc: ConstLoc) -> ConstId;
34 #[salsa::interned] 35 #[salsa::interned]
35 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> StaticId; 36 fn intern_static(&self, loc: StaticLoc) -> StaticId;
36 #[salsa::interned] 37 #[salsa::interned]
37 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> TraitId; 38 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> TraitId;
38 #[salsa::interned] 39 #[salsa::interned]
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index 69846fd1b..225511428 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -52,10 +52,10 @@ impl Documentation {
52 let src = it.parent.child_source(db); 52 let src = it.parent.child_source(db);
53 docs_from_ast(&src.value[it.local_id]) 53 docs_from_ast(&src.value[it.local_id])
54 } 54 }
55 AttrDefId::StaticId(it) => docs_from_ast(&it.source(db).value),
56 AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value), 55 AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value),
57 AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id.to_node(db)), 56 AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id.to_node(db)),
58 AttrDefId::ConstId(it) => docs_from_ast(&it.lookup(db).source(db).value), 57 AttrDefId::ConstId(it) => docs_from_ast(&it.lookup(db).source(db).value),
58 AttrDefId::StaticId(it) => docs_from_ast(&it.lookup(db).source(db).value),
59 AttrDefId::FunctionId(it) => docs_from_ast(&it.lookup(db).source(db).value), 59 AttrDefId::FunctionId(it) => docs_from_ast(&it.lookup(db).source(db).value),
60 AttrDefId::TypeAliasId(it) => docs_from_ast(&it.lookup(db).source(db).value), 60 AttrDefId::TypeAliasId(it) => docs_from_ast(&it.lookup(db).source(db).value),
61 AttrDefId::ImplId(_) => None, 61 AttrDefId::ImplId(_) => None,
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index df951c533..3b9fb0328 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -113,8 +113,8 @@ impl LangItems {
113 T: Into<AttrDefId> + Copy, 113 T: Into<AttrDefId> + Copy,
114 { 114 {
115 let attrs = db.attrs(item.into()); 115 let attrs = db.attrs(item.into());
116 if let Some(lang_item_name) = attrs.find_string_value("lang") { 116 if let Some(lang_item_name) = attrs.by_key("lang").string_value() {
117 self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); 117 self.items.entry(lang_item_name.clone()).or_insert_with(|| constructor(item));
118 } 118 }
119 } 119 }
120} 120}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 1d195d65d..f60feb5fa 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -35,7 +35,7 @@ use std::hash::{Hash, Hasher};
35 35
36use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source}; 36use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source};
37use ra_arena::{impl_arena_id, map::ArenaMap, RawId}; 37use ra_arena::{impl_arena_id, map::ArenaMap, RawId};
38use ra_db::{salsa, CrateId}; 38use ra_db::{impl_intern_key, salsa, CrateId};
39use ra_syntax::{ast, AstNode}; 39use ra_syntax::{ast, AstNode};
40 40
41use crate::{builtin_type::BuiltinType, db::InternDatabase}; 41use crate::{builtin_type::BuiltinType, db::InternDatabase};
@@ -56,19 +56,6 @@ pub struct ModuleId {
56pub struct LocalModuleId(RawId); 56pub struct LocalModuleId(RawId);
57impl_arena_id!(LocalModuleId); 57impl_arena_id!(LocalModuleId);
58 58
59macro_rules! impl_intern_key {
60 ($name:ident) => {
61 impl salsa::InternKey for $name {
62 fn from_intern_id(v: salsa::InternId) -> Self {
63 $name(v)
64 }
65 fn as_intern_id(&self) -> salsa::InternId {
66 self.0
67 }
68 }
69 };
70}
71
72#[derive(Debug)] 59#[derive(Debug)]
73pub struct ItemLoc<N: AstNode> { 60pub struct ItemLoc<N: AstNode> {
74 pub(crate) module: ModuleId, 61 pub(crate) module: ModuleId,
@@ -107,25 +94,10 @@ impl<'a, DB> LocationCtx<&'a DB> {
107 } 94 }
108} 95}
109 96
110impl<'a, DB: AstDatabase + InternDatabase> LocationCtx<&'a DB> {
111 pub fn to_def<N, DEF>(self, ast: &N) -> DEF
112 where
113 N: AstNode,
114 DEF: AstItemDef<N>,
115 {
116 DEF::from_ast(self, ast)
117 }
118}
119
120pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone { 97pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
121 fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self; 98 fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self;
122 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>; 99 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>;
123 100
124 fn from_ast(ctx: LocationCtx<&(impl AstDatabase + InternDatabase)>, ast: &N) -> Self {
125 let items = ctx.db.ast_id_map(ctx.file_id);
126 let item_id = items.ast_id(ast);
127 Self::from_ast_id(ctx, item_id)
128 }
129 fn from_ast_id(ctx: LocationCtx<&impl InternDatabase>, ast_id: FileAstId<N>) -> Self { 101 fn from_ast_id(ctx: LocationCtx<&impl InternDatabase>, ast_id: FileAstId<N>) -> Self {
130 let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) }; 102 let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) };
131 Self::intern(ctx.db, loc) 103 Self::intern(ctx.db, loc)
@@ -258,12 +230,24 @@ impl Lookup for ConstId {
258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 230#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
259pub struct StaticId(salsa::InternId); 231pub struct StaticId(salsa::InternId);
260impl_intern_key!(StaticId); 232impl_intern_key!(StaticId);
261impl AstItemDef<ast::StaticDef> for StaticId { 233
262 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StaticDef>) -> Self { 234#[derive(Debug, Clone, PartialEq, Eq, Hash)]
263 db.intern_static(loc) 235pub struct StaticLoc {
236 pub container: ModuleId,
237 pub ast_id: AstId<ast::StaticDef>,
238}
239
240impl Intern for StaticLoc {
241 type ID = StaticId;
242 fn intern(self, db: &impl db::DefDatabase) -> StaticId {
243 db.intern_static(self)
264 } 244 }
265 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StaticDef> { 245}
266 db.lookup_intern_static(self) 246
247impl Lookup for StaticId {
248 type Data = StaticLoc;
249 fn lookup(&self, db: &impl db::DefDatabase) -> StaticLoc {
250 db.lookup_intern_static(*self)
267 } 251 }
268} 252}
269 253
@@ -494,6 +478,12 @@ impl HasModule for ConstLoc {
494 } 478 }
495} 479}
496 480
481impl HasModule for StaticLoc {
482 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId {
483 self.container
484 }
485}
486
497pub trait HasSource { 487pub trait HasSource {
498 type Value; 488 type Value;
499 fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>; 489 fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>;
@@ -526,6 +516,15 @@ impl HasSource for ConstLoc {
526 } 516 }
527} 517}
528 518
519impl HasSource for StaticLoc {
520 type Value = ast::StaticDef;
521
522 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::StaticDef> {
523 let node = self.ast_id.to_node(db);
524 Source::new(self.ast_id.file_id(), node)
525 }
526}
527
529pub trait HasChildSource { 528pub trait HasChildSource {
530 type ChildId; 529 type ChildId;
531 type Value; 530 type Value;
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index 3b2e99647..f6cf59c5f 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -66,7 +66,7 @@ use ra_arena::Arena;
66use ra_db::{CrateId, Edition, FileId}; 66use ra_db::{CrateId, Edition, FileId};
67use ra_prof::profile; 67use ra_prof::profile;
68use ra_syntax::ast; 68use ra_syntax::ast;
69use rustc_hash::{FxHashMap, FxHashSet}; 69use rustc_hash::FxHashMap;
70 70
71use crate::{ 71use crate::{
72 builtin_type::BuiltinType, 72 builtin_type::BuiltinType,
@@ -90,18 +90,6 @@ pub struct CrateDefMap {
90 root: LocalModuleId, 90 root: LocalModuleId,
91 modules: Arena<LocalModuleId, ModuleData>, 91 modules: Arena<LocalModuleId, ModuleData>,
92 92
93 /// Some macros are not well-behavior, which leads to infinite loop
94 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
95 /// We mark it down and skip it in collector
96 ///
97 /// FIXME:
98 /// Right now it only handle a poison macro in a single crate,
99 /// such that if other crate try to call that macro,
100 /// the whole process will do again until it became poisoned in that crate.
101 /// We should handle this macro set globally
102 /// However, do we want to put it as a global variable?
103 poison_macros: FxHashSet<MacroDefId>,
104
105 diagnostics: Vec<DefDiagnostic>, 93 diagnostics: Vec<DefDiagnostic>,
106} 94}
107 95
@@ -234,7 +222,6 @@ impl CrateDefMap {
234 prelude: None, 222 prelude: None,
235 root, 223 root,
236 modules, 224 modules,
237 poison_macros: FxHashSet::default(),
238 diagnostics: Vec::new(), 225 diagnostics: Vec::new(),
239 } 226 }
240 }; 227 };
@@ -267,16 +254,6 @@ impl CrateDefMap {
267 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) 254 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
268 } 255 }
269 256
270 pub fn resolve_path(
271 &self,
272 db: &impl DefDatabase,
273 original_module: LocalModuleId,
274 path: &Path,
275 ) -> (PerNs, Option<usize>) {
276 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
277 (res.resolved_def, res.segment_index)
278 }
279
280 pub fn modules(&self) -> impl Iterator<Item = LocalModuleId> + '_ { 257 pub fn modules(&self) -> impl Iterator<Item = LocalModuleId> + '_ {
281 self.modules.iter().map(|(id, _data)| id) 258 self.modules.iter().map(|(id, _data)| id)
282 } 259 }
@@ -287,6 +264,16 @@ impl CrateDefMap {
287 .filter(move |(_id, data)| data.definition == Some(file_id)) 264 .filter(move |(_id, data)| data.definition == Some(file_id))
288 .map(|(id, _data)| id) 265 .map(|(id, _data)| id)
289 } 266 }
267
268 pub(crate) fn resolve_path(
269 &self,
270 db: &impl DefDatabase,
271 original_module: LocalModuleId,
272 path: &Path,
273 ) -> (PerNs, Option<usize>) {
274 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
275 (res.resolved_def, res.segment_index)
276 }
290} 277}
291 278
292impl ModuleData { 279impl ModuleData {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index b02364e86..7a5f90327 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -7,8 +7,8 @@ use hir_expand::{
7}; 7};
8use ra_cfg::CfgOptions; 8use ra_cfg::CfgOptions;
9use ra_db::{CrateId, FileId}; 9use ra_db::{CrateId, FileId};
10use ra_syntax::{ast, SmolStr}; 10use ra_syntax::ast;
11use rustc_hash::FxHashMap; 11use rustc_hash::{FxHashMap, FxHashSet};
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
14use crate::{ 14use crate::{
@@ -21,7 +21,7 @@ use crate::{
21 path::{Path, PathKind}, 21 path::{Path, PathKind},
22 per_ns::PerNs, 22 per_ns::PerNs,
23 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId, 23 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId,
24 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, 24 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId,
25 StructOrUnionId, TraitId, TypeAliasLoc, UnionId, 25 StructOrUnionId, TraitId, TypeAliasLoc, UnionId,
26}; 26};
27 27
@@ -57,6 +57,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
57 unexpanded_macros: Vec::new(), 57 unexpanded_macros: Vec::new(),
58 mod_dirs: FxHashMap::default(), 58 mod_dirs: FxHashMap::default(),
59 macro_stack_monitor: MacroStackMonitor::default(), 59 macro_stack_monitor: MacroStackMonitor::default(),
60 poison_macros: FxHashSet::default(),
60 cfg_options, 61 cfg_options,
61 }; 62 };
62 collector.collect(); 63 collector.collect();
@@ -103,6 +104,17 @@ struct DefCollector<'a, DB> {
103 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly 104 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
104 /// To prevent stack overflow, we add a deep counter here for prevent that. 105 /// To prevent stack overflow, we add a deep counter here for prevent that.
105 macro_stack_monitor: MacroStackMonitor, 106 macro_stack_monitor: MacroStackMonitor,
107 /// Some macros are not well-behavior, which leads to infinite loop
108 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
109 /// We mark it down and skip it in collector
110 ///
111 /// FIXME:
112 /// Right now it only handle a poison macro in a single crate,
113 /// such that if other crate try to call that macro,
114 /// the whole process will do again until it became poisoned in that crate.
115 /// We should handle this macro set globally
116 /// However, do we want to put it as a global variable?
117 poison_macros: FxHashSet<MacroDefId>,
106 118
107 cfg_options: &'a CfgOptions, 119 cfg_options: &'a CfgOptions,
108} 120}
@@ -489,7 +501,7 @@ where
489 macro_call_id: MacroCallId, 501 macro_call_id: MacroCallId,
490 macro_def_id: MacroDefId, 502 macro_def_id: MacroDefId,
491 ) { 503 ) {
492 if self.def_map.poison_macros.contains(&macro_def_id) { 504 if self.poison_macros.contains(&macro_def_id) {
493 return; 505 return;
494 } 506 }
495 507
@@ -509,7 +521,7 @@ where
509 .collect(raw_items.items()); 521 .collect(raw_items.items());
510 } else { 522 } else {
511 log::error!("Too deep macro expansion: {:?}", macro_call_id); 523 log::error!("Too deep macro expansion: {:?}", macro_call_id);
512 self.def_map.poison_macros.insert(macro_def_id); 524 self.poison_macros.insert(macro_def_id);
513 } 525 }
514 526
515 self.macro_stack_monitor.decrease(macro_def_id); 527 self.macro_stack_monitor.decrease(macro_def_id);
@@ -587,8 +599,8 @@ where
587 } 599 }
588 600
589 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) { 601 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
590 let path_attr = self.path_attr(attrs); 602 let path_attr = attrs.by_key("path").string_value();
591 let is_macro_use = attrs.has_atom("macro_use"); 603 let is_macro_use = attrs.by_key("macro_use").exists();
592 match module { 604 match module {
593 // inline module, just recurse 605 // inline module, just recurse
594 raw::ModuleData::Definition { name, items, ast_id } => { 606 raw::ModuleData::Definition { name, items, ast_id } => {
@@ -703,7 +715,10 @@ where
703 PerNs::values(def.into()) 715 PerNs::values(def.into())
704 } 716 }
705 raw::DefKind::Static(ast_id) => { 717 raw::DefKind::Static(ast_id) => {
706 PerNs::values(StaticId::from_ast_id(ctx, ast_id).into()) 718 let def = StaticLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) }
719 .intern(self.def_collector.db);
720
721 PerNs::values(def.into())
707 } 722 }
708 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), 723 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()),
709 raw::DefKind::TypeAlias(ast_id) => { 724 raw::DefKind::TypeAlias(ast_id) => {
@@ -781,11 +796,11 @@ where
781 } 796 }
782 797
783 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { 798 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
784 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) 799 // FIXME: handle cfg_attr :-)
785 } 800 attrs
786 801 .by_key("cfg")
787 fn path_attr<'a>(&self, attrs: &'a Attrs) -> Option<&'a SmolStr> { 802 .tt_values()
788 attrs.iter().find_map(|attr| attr.as_path()) 803 .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
789 } 804 }
790} 805}
791 806
@@ -807,7 +822,7 @@ mod tests {
807 db: &impl DefDatabase, 822 db: &impl DefDatabase,
808 def_map: CrateDefMap, 823 def_map: CrateDefMap,
809 monitor: MacroStackMonitor, 824 monitor: MacroStackMonitor,
810 ) -> CrateDefMap { 825 ) -> (CrateDefMap, FxHashSet<MacroDefId>) {
811 let mut collector = DefCollector { 826 let mut collector = DefCollector {
812 db, 827 db,
813 def_map, 828 def_map,
@@ -816,13 +831,18 @@ mod tests {
816 unexpanded_macros: Vec::new(), 831 unexpanded_macros: Vec::new(),
817 mod_dirs: FxHashMap::default(), 832 mod_dirs: FxHashMap::default(),
818 macro_stack_monitor: monitor, 833 macro_stack_monitor: monitor,
834 poison_macros: FxHashSet::default(),
819 cfg_options: &CfgOptions::default(), 835 cfg_options: &CfgOptions::default(),
820 }; 836 };
821 collector.collect(); 837 collector.collect();
822 collector.finish() 838 (collector.def_map, collector.poison_macros)
823 } 839 }
824 840
825 fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap { 841 fn do_limited_resolve(
842 code: &str,
843 limit: u32,
844 poison_limit: u32,
845 ) -> (CrateDefMap, FxHashSet<MacroDefId>) {
826 let (db, _file_id) = TestDB::with_single_file(&code); 846 let (db, _file_id) = TestDB::with_single_file(&code);
827 let krate = db.test_crate(); 847 let krate = db.test_crate();
828 848
@@ -837,7 +857,6 @@ mod tests {
837 prelude: None, 857 prelude: None,
838 root, 858 root,
839 modules, 859 modules,
840 poison_macros: FxHashSet::default(),
841 diagnostics: Vec::new(), 860 diagnostics: Vec::new(),
842 } 861 }
843 }; 862 };
@@ -867,7 +886,7 @@ foo!(KABOOM);
867 886
868 #[test] 887 #[test]
869 fn test_macro_expand_poisoned() { 888 fn test_macro_expand_poisoned() {
870 let def = do_limited_resolve( 889 let (_, poison_macros) = do_limited_resolve(
871 r#" 890 r#"
872 macro_rules! foo { 891 macro_rules! foo {
873 ($ty:ty) => { foo!($ty); } 892 ($ty:ty) => { foo!($ty); }
@@ -878,12 +897,12 @@ foo!(KABOOM);
878 16, 897 16,
879 ); 898 );
880 899
881 assert_eq!(def.poison_macros.len(), 1); 900 assert_eq!(poison_macros.len(), 1);
882 } 901 }
883 902
884 #[test] 903 #[test]
885 fn test_macro_expand_normal() { 904 fn test_macro_expand_normal() {
886 let def = do_limited_resolve( 905 let (_, poison_macros) = do_limited_resolve(
887 r#" 906 r#"
888 macro_rules! foo { 907 macro_rules! foo {
889 ($ident:ident) => { struct $ident {} } 908 ($ident:ident) => { struct $ident {} }
@@ -894,6 +913,6 @@ foo!(Bar);
894 16, 913 16,
895 ); 914 );
896 915
897 assert_eq!(def.poison_macros.len(), 0); 916 assert_eq!(poison_macros.len(), 0);
898 } 917 }
899} 918}
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 552cbe544..198578753 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -17,10 +17,7 @@ use ra_syntax::{
17use test_utils::tested_by; 17use test_utils::tested_by;
18 18
19use crate::{ 19use crate::{
20 attr::{Attr, Attrs}, 20 attr::Attrs, db::DefDatabase, path::Path, FileAstId, HirFileId, LocalImportId, Source,
21 db::DefDatabase,
22 path::Path,
23 FileAstId, HirFileId, LocalImportId, Source,
24}; 21};
25 22
26/// `RawItems` is a set of top-level items in a file (except for impls). 23/// `RawItems` is a set of top-level items in a file (except for impls).
@@ -407,6 +404,6 @@ impl RawItemsCollector {
407 } 404 }
408 405
409 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { 406 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
410 Attr::from_attrs_owner(item, &self.hygiene) 407 Attrs::new(item, &self.hygiene)
411 } 408 }
412} 409}
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index b56de44dd..4ff0a091b 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -540,7 +540,7 @@ impl HasResolver for ConstId {
540 540
541impl HasResolver for StaticId { 541impl HasResolver for StaticId {
542 fn resolver(self, db: &impl DefDatabase) -> Resolver { 542 fn resolver(self, db: &impl DefDatabase) -> Resolver {
543 self.module(db).resolver(db) 543 self.lookup(db).container.resolver(db)
544 } 544 }
545} 545}
546 546
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 896ad1517..bac3f7582 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -288,7 +288,7 @@ impl Completions {
288} 288}
289 289
290fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool { 290fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool {
291 node.attrs(db).has_atom("deprecated") 291 node.attrs(db).by_key("deprecated").exists()
292} 292}
293 293
294fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { 294fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool {