diff options
Diffstat (limited to 'crates')
31 files changed, 286 insertions, 282 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::{ | |||
15 | pub use relative_path::{RelativePath, RelativePathBuf}; | 15 | pub use relative_path::{RelativePath, RelativePathBuf}; |
16 | pub use salsa; | 16 | pub use salsa; |
17 | 17 | ||
18 | #[macro_export] | ||
19 | macro_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 | |||
18 | pub trait CheckCanceled { | 32 | pub 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..b3e2ff1c2 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 | }; |
18 | use hir_expand::{ | 19 | use hir_expand::{ |
19 | diagnostics::DiagnosticSink, | 20 | diagnostics::DiagnosticSink, |
20 | name::{self, AsName}, | 21 | name::{self, AsName}, |
21 | AstId, | 22 | AstId, MacroDefId, |
22 | }; | 23 | }; |
23 | use ra_db::{CrateId, Edition, FileId, FilePosition}; | 24 | use ra_db::{CrateId, Edition, FileId, FilePosition}; |
24 | use ra_syntax::{ast, AstNode, SyntaxNode}; | 25 | use ra_syntax::{ast, AstNode, SyntaxNode}; |
@@ -26,10 +27,6 @@ use ra_syntax::{ast, AstNode, SyntaxNode}; | |||
26 | use crate::{ | 27 | use 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 | ||
738 | impl Static { | 735 | impl 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> { |
@@ -1040,7 +1037,7 @@ impl From<PerNs> for ScopeDef { | |||
1040 | .or_else(|| def.take_values()) | 1037 | .or_else(|| def.take_values()) |
1041 | .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into())) | 1038 | .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into())) |
1042 | .or_else(|| { | 1039 | .or_else(|| { |
1043 | def.get_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into())) | 1040 | def.take_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into())) |
1044 | }) | 1041 | }) |
1045 | .unwrap_or(ScopeDef::Unknown) | 1042 | .unwrap_or(ScopeDef::Unknown) |
1046 | } | 1043 | } |
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 | ||
3 | use hir_def::{HasChildSource, HasSource as _, Lookup, VariantId}; | 3 | use hir_def::{AstItemDef, HasChildSource, HasSource as _, Lookup, VariantId}; |
4 | use hir_expand::either::Either; | 4 | use hir_expand::either::Either; |
5 | use ra_syntax::ast::{self, AstNode}; | 5 | use ra_syntax::ast::{self, AstNode}; |
6 | 6 | ||
7 | use crate::{ | 7 | use 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 { | |||
89 | impl HasSource for Static { | 88 | impl 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 | } |
95 | impl HasSource for Trait { | 94 | impl 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; | |||
5 | use ra_db::salsa; | 5 | use ra_db::salsa; |
6 | 6 | ||
7 | use crate::{ | 7 | use 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 | ||
23 | use std::fmt; | 23 | use std::fmt; |
24 | 24 | ||
25 | use hir_expand::HirFileId; | ||
25 | use ra_db::{CrateId, FileId}; | 26 | use ra_db::{CrateId, FileId}; |
26 | 27 | ||
27 | use crate::{db::HirDatabase, Crate, HirFileId, Module, Name}; | 28 | use crate::{db::HirDatabase, Crate, Module, Name}; |
28 | 29 | ||
29 | impl Crate { | 30 | impl 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 | ||
3 | use std::any::Any; | 3 | use std::any::Any; |
4 | 4 | ||
5 | use hir_expand::HirFileId; | ||
5 | use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; | 6 | use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; |
6 | 7 | ||
7 | use crate::{db::AstDatabase, HirFileId, Name, Source}; | 8 | use crate::{db::AstDatabase, Name, Source}; |
8 | 9 | ||
9 | pub use hir_def::diagnostics::UnresolvedModule; | 10 | pub use hir_def::diagnostics::UnresolvedModule; |
10 | pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; | 11 | pub 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 | ||
3 | use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId}; | 3 | use hir_def::{AstItemDef, LocationCtx, ModuleId, StructId, StructOrUnionId, UnionId}; |
4 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; | 4 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; |
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | ast::{self, AstNode, NameOwner}, | 6 | ast::{self, AstNode, NameOwner}, |
@@ -9,7 +9,6 @@ use ra_syntax::{ | |||
9 | 9 | ||
10 | use crate::{ | 10 | use 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 { | |||
105 | impl FromSource for Static { | 104 | impl 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 | |||
112 | impl FromSource for TypeAlias { | 122 | impl 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 | ||
278 | enum Container { | 290 | enum 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 | |||
8 | use ra_db::salsa; | ||
9 | |||
10 | pub use hir_def::{ | ||
11 | AstItemDef, ConstId, EnumId, FunctionId, ItemLoc, LocationCtx, StaticId, StructId, TraitId, | ||
12 | TypeAliasId, | ||
13 | }; | ||
14 | pub use hir_expand::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, MacroFileKind}; | ||
15 | |||
16 | macro_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)] | ||
33 | pub struct TypeCtorId(salsa::InternId); | ||
34 | impl_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)] | ||
38 | pub struct GlobalImplId(salsa::InternId); | ||
39 | impl_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)] | ||
44 | pub struct AssocTyValueId(salsa::InternId); | ||
45 | impl_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; | |||
31 | pub mod db; | 31 | pub mod db; |
32 | pub mod source_binder; | 32 | pub mod source_binder; |
33 | 33 | ||
34 | mod ids; | ||
35 | mod ty; | 34 | mod ty; |
36 | mod impl_block; | 35 | mod impl_block; |
37 | mod expr; | 36 | mod 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 | }; |
76 | pub use hir_expand::{either::Either, name::Name, Source}; | 74 | pub 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 | }; |
16 | use hir_expand::{name::AsName, AstId, MacroCallId, MacroCallLoc, MacroFileKind, Source}; | 16 | use hir_expand::{ |
17 | name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind, Source, | ||
18 | }; | ||
17 | use ra_syntax::{ | 19 | use 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::{ | |||
24 | use crate::{ | 26 | use 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 | ||
34 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { | 35 | fn 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 |
548 | fn to_macro_file_kind(macro_call: &ast::MacroCall) -> MacroFileKind { | 545 | fn 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; | |||
18 | use std::{fmt, iter, mem}; | 18 | use std::{fmt, iter, mem}; |
19 | 19 | ||
20 | use hir_def::{generics::GenericParams, AdtId}; | 20 | use hir_def::{generics::GenericParams, AdtId}; |
21 | use ra_db::{impl_intern_key, salsa}; | ||
21 | 22 | ||
22 | use crate::{ | 23 | use 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)] | ||
122 | pub struct TypeCtorId(salsa::InternId); | ||
123 | impl_intern_key!(TypeCtorId); | ||
124 | |||
117 | impl TypeCtor { | 125 | impl 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 | ||
4 | use chalk_ir::{cast::Cast, family::ChalkIr}; | 4 | use chalk_ir::{cast::Cast, family::ChalkIr}; |
5 | use log::debug; | 5 | use log::debug; |
6 | use ra_db::salsa; | 6 | use ra_db::{impl_intern_key, salsa}; |
7 | use ra_prof::profile; | 7 | use ra_prof::profile; |
8 | use rustc_hash::FxHashSet; | 8 | use 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)] | ||
309 | pub struct GlobalImplId(salsa::InternId); | ||
310 | impl_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)] | ||
325 | pub struct AssocTyValueId(salsa::InternId); | ||
326 | impl_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 | ||
850 | impl From<chalk_ir::StructId> for crate::ids::TypeCtorId { | 850 | impl 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 | ||
856 | impl From<crate::ids::TypeCtorId> for chalk_ir::StructId { | 856 | impl 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 | ||
862 | impl From<chalk_ir::ImplId> for crate::ids::GlobalImplId { | 862 | impl 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 | ||
868 | impl From<crate::ids::GlobalImplId> for chalk_ir::ImplId { | 868 | impl 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 | ||
874 | impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ids::AssocTyValueId { | 874 | impl 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 | ||
880 | impl From<crate::ids::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { | 880 | impl 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 | ||
3 | use std::{ops, sync::Arc}; | 3 | use std::{ops, sync::Arc}; |
4 | 4 | ||
5 | use hir_expand::{either::Either, hygiene::Hygiene, AstId}; | 5 | use hir_expand::{either::Either, hygiene::Hygiene, AstId, Source}; |
6 | use mbe::ast_to_token_tree; | 6 | use mbe::ast_to_token_tree; |
7 | use ra_cfg::CfgOptions; | ||
8 | use ra_syntax::{ | 7 | use 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 | ||
102 | impl Attr { | 104 | impl 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 { | 123 | pub 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 { | 128 | impl<'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 | ||
171 | fn attrs_from_loc<T, D>(node: T, db: &D) -> Attrs | 164 | fn 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..c06997cf1 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 | ||
23 | pub struct Expander { | 23 | pub struct Expander { |
@@ -82,7 +82,7 @@ impl Expander { | |||
82 | } | 82 | } |
83 | 83 | ||
84 | fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { | 84 | fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { |
85 | self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros() | 85 | self.crate_def_map.resolve_path(db, self.module.module_id, path).0.take_macros() |
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
@@ -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..68bea34df 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -200,18 +200,17 @@ pub struct ConstData { | |||
200 | impl ConstData { | 200 | impl ConstData { |
201 | pub(crate) fn const_data_query(db: &impl DefDatabase, konst: ConstId) -> Arc<ConstData> { | 201 | pub(crate) fn const_data_query(db: &impl DefDatabase, konst: ConstId) -> Arc<ConstData> { |
202 | let node = konst.lookup(db).source(db).value; | 202 | let node = konst.lookup(db).source(db).value; |
203 | const_data_for(&node) | 203 | Arc::new(ConstData::new(&node)) |
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 | Arc::new(ConstData::new(&node)) |
209 | } | 209 | } |
210 | } | ||
211 | 210 | ||
212 | fn const_data_for<N: NameOwner + TypeAscriptionOwner>(node: &N) -> Arc<ConstData> { | 211 | fn new<N: NameOwner + TypeAscriptionOwner>(node: &N) -> ConstData { |
213 | let name = node.name().map(|n| n.as_name()); | 212 | let name = node.name().map(|n| n.as_name()); |
214 | let type_ref = TypeRef::from_ast_opt(node.ascribed_type()); | 213 | let type_ref = TypeRef::from_ast_opt(node.ascribed_type()); |
215 | let sig = ConstData { name, type_ref }; | 214 | ConstData { name, type_ref } |
216 | Arc::new(sig) | 215 | } |
217 | } | 216 | } |
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..90a8627bc 100644 --- a/crates/ra_hir_def/src/docs.rs +++ b/crates/ra_hir_def/src/docs.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Defines hir documentation. |
2 | //! | ||
3 | //! This really shouldn't exist, instead, we should deshugar doc comments into attributes, see | ||
4 | //! https://github.com/rust-analyzer/rust-analyzer/issues/2148#issuecomment-550519102 | ||
2 | 5 | ||
3 | use std::sync::Arc; | 6 | use std::sync::Arc; |
4 | 7 | ||
@@ -52,10 +55,10 @@ impl Documentation { | |||
52 | let src = it.parent.child_source(db); | 55 | let src = it.parent.child_source(db); |
53 | docs_from_ast(&src.value[it.local_id]) | 56 | docs_from_ast(&src.value[it.local_id]) |
54 | } | 57 | } |
55 | AttrDefId::StaticId(it) => docs_from_ast(&it.source(db).value), | ||
56 | AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value), | 58 | AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value), |
57 | AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id.to_node(db)), | 59 | 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), | 60 | AttrDefId::ConstId(it) => docs_from_ast(&it.lookup(db).source(db).value), |
61 | 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), | 62 | 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), | 63 | AttrDefId::TypeAliasId(it) => docs_from_ast(&it.lookup(db).source(db).value), |
61 | AttrDefId::ImplId(_) => None, | 64 | 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..f63c3dd64 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -8,20 +8,23 @@ | |||
8 | //! actually true. | 8 | //! actually true. |
9 | 9 | ||
10 | pub mod db; | 10 | pub mod db; |
11 | |||
11 | pub mod attr; | 12 | pub mod attr; |
12 | pub mod path; | 13 | pub mod path; |
13 | pub mod type_ref; | 14 | pub mod type_ref; |
14 | pub mod builtin_type; | 15 | pub mod builtin_type; |
15 | pub mod adt; | ||
16 | pub mod diagnostics; | 16 | pub mod diagnostics; |
17 | pub mod expr; | 17 | pub mod per_ns; |
18 | pub mod body; | 18 | |
19 | pub mod generics; | 19 | pub mod adt; |
20 | pub mod resolver; | ||
21 | pub mod data; | 20 | pub mod data; |
21 | pub mod generics; | ||
22 | pub mod lang_item; | 22 | pub mod lang_item; |
23 | pub mod docs; | 23 | pub mod docs; |
24 | pub mod per_ns; | 24 | |
25 | pub mod expr; | ||
26 | pub mod body; | ||
27 | pub mod resolver; | ||
25 | 28 | ||
26 | mod trace; | 29 | mod trace; |
27 | mod nameres; | 30 | mod nameres; |
@@ -35,7 +38,7 @@ use std::hash::{Hash, Hasher}; | |||
35 | 38 | ||
36 | use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source}; | 39 | use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source}; |
37 | use ra_arena::{impl_arena_id, map::ArenaMap, RawId}; | 40 | use ra_arena::{impl_arena_id, map::ArenaMap, RawId}; |
38 | use ra_db::{salsa, CrateId}; | 41 | use ra_db::{impl_intern_key, salsa, CrateId}; |
39 | use ra_syntax::{ast, AstNode}; | 42 | use ra_syntax::{ast, AstNode}; |
40 | 43 | ||
41 | use crate::{builtin_type::BuiltinType, db::InternDatabase}; | 44 | use crate::{builtin_type::BuiltinType, db::InternDatabase}; |
@@ -56,19 +59,6 @@ pub struct ModuleId { | |||
56 | pub struct LocalModuleId(RawId); | 59 | pub struct LocalModuleId(RawId); |
57 | impl_arena_id!(LocalModuleId); | 60 | impl_arena_id!(LocalModuleId); |
58 | 61 | ||
59 | macro_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)] | 62 | #[derive(Debug)] |
73 | pub struct ItemLoc<N: AstNode> { | 63 | pub struct ItemLoc<N: AstNode> { |
74 | pub(crate) module: ModuleId, | 64 | pub(crate) module: ModuleId, |
@@ -107,25 +97,10 @@ impl<'a, DB> LocationCtx<&'a DB> { | |||
107 | } | 97 | } |
108 | } | 98 | } |
109 | 99 | ||
110 | impl<'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 | |||
120 | pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone { | 100 | pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone { |
121 | fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self; | 101 | fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self; |
122 | fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>; | 102 | fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>; |
123 | 103 | ||
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 { | 104 | 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) }; | 105 | let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) }; |
131 | Self::intern(ctx.db, loc) | 106 | Self::intern(ctx.db, loc) |
@@ -258,12 +233,24 @@ impl Lookup for ConstId { | |||
258 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 233 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
259 | pub struct StaticId(salsa::InternId); | 234 | pub struct StaticId(salsa::InternId); |
260 | impl_intern_key!(StaticId); | 235 | impl_intern_key!(StaticId); |
261 | impl AstItemDef<ast::StaticDef> for StaticId { | 236 | |
262 | fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StaticDef>) -> Self { | 237 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
263 | db.intern_static(loc) | 238 | pub struct StaticLoc { |
239 | pub container: ModuleId, | ||
240 | pub ast_id: AstId<ast::StaticDef>, | ||
241 | } | ||
242 | |||
243 | impl Intern for StaticLoc { | ||
244 | type ID = StaticId; | ||
245 | fn intern(self, db: &impl db::DefDatabase) -> StaticId { | ||
246 | db.intern_static(self) | ||
264 | } | 247 | } |
265 | fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StaticDef> { | 248 | } |
266 | db.lookup_intern_static(self) | 249 | |
250 | impl Lookup for StaticId { | ||
251 | type Data = StaticLoc; | ||
252 | fn lookup(&self, db: &impl db::DefDatabase) -> StaticLoc { | ||
253 | db.lookup_intern_static(*self) | ||
267 | } | 254 | } |
268 | } | 255 | } |
269 | 256 | ||
@@ -494,6 +481,12 @@ impl HasModule for ConstLoc { | |||
494 | } | 481 | } |
495 | } | 482 | } |
496 | 483 | ||
484 | impl HasModule for StaticLoc { | ||
485 | fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { | ||
486 | self.container | ||
487 | } | ||
488 | } | ||
489 | |||
497 | pub trait HasSource { | 490 | pub trait HasSource { |
498 | type Value; | 491 | type Value; |
499 | fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>; | 492 | fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>; |
@@ -526,6 +519,15 @@ impl HasSource for ConstLoc { | |||
526 | } | 519 | } |
527 | } | 520 | } |
528 | 521 | ||
522 | impl HasSource for StaticLoc { | ||
523 | type Value = ast::StaticDef; | ||
524 | |||
525 | fn source(&self, db: &impl db::DefDatabase) -> Source<ast::StaticDef> { | ||
526 | let node = self.ast_id.to_node(db); | ||
527 | Source::new(self.ast_id.file_id(), node) | ||
528 | } | ||
529 | } | ||
530 | |||
529 | pub trait HasChildSource { | 531 | pub trait HasChildSource { |
530 | type ChildId; | 532 | type ChildId; |
531 | type Value; | 533 | type Value; |
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 3b2e99647..5919771b0 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; | |||
66 | use ra_db::{CrateId, Edition, FileId}; | 66 | use ra_db::{CrateId, Edition, FileId}; |
67 | use ra_prof::profile; | 67 | use ra_prof::profile; |
68 | use ra_syntax::ast; | 68 | use ra_syntax::ast; |
69 | use rustc_hash::{FxHashMap, FxHashSet}; | 69 | use rustc_hash::FxHashMap; |
70 | 70 | ||
71 | use crate::{ | 71 | use 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 | ||
@@ -181,7 +169,7 @@ impl ModuleScope { | |||
181 | pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { | 169 | pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { |
182 | self.items | 170 | self.items |
183 | .iter() | 171 | .iter() |
184 | .filter_map(|(name, res)| res.def.get_macros().map(|macro_| (name, macro_))) | 172 | .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) |
185 | } | 173 | } |
186 | 174 | ||
187 | /// Iterate over all legacy textual scoped macros visable at the end of the module | 175 | /// Iterate over all legacy textual scoped macros visable at the end of the module |
@@ -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 | ||
292 | impl ModuleData { | 279 | impl ModuleData { |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index b02364e86..df01a20e1 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 | }; |
8 | use ra_cfg::CfgOptions; | 8 | use ra_cfg::CfgOptions; |
9 | use ra_db::{CrateId, FileId}; | 9 | use ra_db::{CrateId, FileId}; |
10 | use ra_syntax::{ast, SmolStr}; | 10 | use ra_syntax::ast; |
11 | use rustc_hash::FxHashMap; | 11 | use rustc_hash::{FxHashMap, FxHashSet}; |
12 | use test_utils::tested_by; | 12 | use test_utils::tested_by; |
13 | 13 | ||
14 | use crate::{ | 14 | use 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 | } |
@@ -464,7 +476,7 @@ where | |||
464 | path, | 476 | path, |
465 | ); | 477 | ); |
466 | 478 | ||
467 | if let Some(def) = resolved_res.resolved_def.get_macros() { | 479 | if let Some(def) = resolved_res.resolved_def.take_macros() { |
468 | let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id: *ast_id }); | 480 | let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id: *ast_id }); |
469 | resolved.push((*module_id, call_id, def)); | 481 | resolved.push((*module_id, call_id, def)); |
470 | res = ReachedFixedPoint::No; | 482 | res = ReachedFixedPoint::No; |
@@ -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(¯o_def_id) { | 504 | if self.poison_macros.contains(¯o_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..2ec84f2cc 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs | |||
@@ -1,4 +1,9 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Lowers syntax tree of a rust file into a raw representation of containing |
2 | //! items, *without* attaching them to a module structure. | ||
3 | //! | ||
4 | //! That is, raw items don't have semantics, just as syntax, but, unlike syntax, | ||
5 | //! they don't change with trivial source code edits, making them a great tool | ||
6 | //! for building salsa recomputation firewalls. | ||
2 | 7 | ||
3 | use std::{ops::Index, sync::Arc}; | 8 | use std::{ops::Index, sync::Arc}; |
4 | 9 | ||
@@ -17,10 +22,7 @@ use ra_syntax::{ | |||
17 | use test_utils::tested_by; | 22 | use test_utils::tested_by; |
18 | 23 | ||
19 | use crate::{ | 24 | use crate::{ |
20 | attr::{Attr, Attrs}, | 25 | attr::Attrs, db::DefDatabase, path::Path, FileAstId, HirFileId, LocalImportId, Source, |
21 | db::DefDatabase, | ||
22 | path::Path, | ||
23 | FileAstId, HirFileId, LocalImportId, Source, | ||
24 | }; | 26 | }; |
25 | 27 | ||
26 | /// `RawItems` is a set of top-level items in a file (except for impls). | 28 | /// `RawItems` is a set of top-level items in a file (except for impls). |
@@ -407,6 +409,6 @@ impl RawItemsCollector { | |||
407 | } | 409 | } |
408 | 410 | ||
409 | fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | 411 | fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { |
410 | Attr::from_attrs_owner(item, &self.hygiene) | 412 | Attrs::new(item, &self.hygiene) |
411 | } | 413 | } |
412 | } | 414 | } |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 626ebffdc..7b2723d57 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`. |
2 | 2 | ||
3 | use std::{iter, sync::Arc}; | 3 | use std::{iter, sync::Arc}; |
4 | 4 | ||
@@ -66,7 +66,7 @@ pub enum PathKind { | |||
66 | 66 | ||
67 | impl Path { | 67 | impl Path { |
68 | /// Calls `cb` with all paths, represented by this use item. | 68 | /// Calls `cb` with all paths, represented by this use item. |
69 | pub fn expand_use_item( | 69 | pub(crate) fn expand_use_item( |
70 | item_src: Source<ast::UseItem>, | 70 | item_src: Source<ast::UseItem>, |
71 | hygiene: &Hygiene, | 71 | hygiene: &Hygiene, |
72 | mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), | 72 | mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), |
@@ -76,7 +76,10 @@ impl Path { | |||
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> Path { | 79 | pub(crate) fn from_simple_segments( |
80 | kind: PathKind, | ||
81 | segments: impl IntoIterator<Item = Name>, | ||
82 | ) -> Path { | ||
80 | Path { | 83 | Path { |
81 | kind, | 84 | kind, |
82 | segments: segments | 85 | segments: segments |
@@ -94,7 +97,7 @@ impl Path { | |||
94 | 97 | ||
95 | /// Converts an `ast::Path` to `Path`. Works with use trees. | 98 | /// Converts an `ast::Path` to `Path`. Works with use trees. |
96 | /// It correctly handles `$crate` based path from macro call. | 99 | /// It correctly handles `$crate` based path from macro call. |
97 | pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> { | 100 | pub(crate) fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> { |
98 | let mut kind = PathKind::Plain; | 101 | let mut kind = PathKind::Plain; |
99 | let mut segments = Vec::new(); | 102 | let mut segments = Vec::new(); |
100 | loop { | 103 | loop { |
@@ -227,7 +230,7 @@ impl Path { | |||
227 | } | 230 | } |
228 | 231 | ||
229 | impl GenericArgs { | 232 | impl GenericArgs { |
230 | pub fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> { | 233 | pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> { |
231 | let mut args = Vec::new(); | 234 | let mut args = Vec::new(); |
232 | for type_arg in node.type_args() { | 235 | for type_arg in node.type_args() { |
233 | let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); | 236 | let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); |
diff --git a/crates/ra_hir_def/src/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs index 717ed1ef9..06ef6c9fc 100644 --- a/crates/ra_hir_def/src/per_ns.rs +++ b/crates/ra_hir_def/src/per_ns.rs | |||
@@ -44,10 +44,6 @@ impl PerNs { | |||
44 | self.types.is_none() && self.values.is_none() && self.macros.is_none() | 44 | self.types.is_none() && self.values.is_none() && self.macros.is_none() |
45 | } | 45 | } |
46 | 46 | ||
47 | pub fn is_all(&self) -> bool { | ||
48 | self.types.is_some() && self.values.is_some() && self.macros.is_some() | ||
49 | } | ||
50 | |||
51 | pub fn take_types(self) -> Option<ModuleDefId> { | 47 | pub fn take_types(self) -> Option<ModuleDefId> { |
52 | self.types | 48 | self.types |
53 | } | 49 | } |
@@ -56,14 +52,10 @@ impl PerNs { | |||
56 | self.values | 52 | self.values |
57 | } | 53 | } |
58 | 54 | ||
59 | pub fn get_macros(&self) -> Option<MacroDefId> { | 55 | pub fn take_macros(self) -> Option<MacroDefId> { |
60 | self.macros | 56 | self.macros |
61 | } | 57 | } |
62 | 58 | ||
63 | pub fn only_macros(&self) -> PerNs { | ||
64 | PerNs { types: None, values: None, macros: self.macros } | ||
65 | } | ||
66 | |||
67 | pub fn or(self, other: PerNs) -> PerNs { | 59 | pub fn or(self, other: PerNs) -> PerNs { |
68 | PerNs { | 60 | PerNs { |
69 | types: self.types.or(other.types), | 61 | types: self.types.or(other.types), |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index b56de44dd..7182b8a4d 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -308,7 +308,7 @@ impl Resolver { | |||
308 | 308 | ||
309 | pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { | 309 | pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { |
310 | let (item_map, module) = self.module()?; | 310 | let (item_map, module) = self.module()?; |
311 | item_map.resolve_path(db, module, path).0.get_macros() | 311 | item_map.resolve_path(db, module, path).0.take_macros() |
312 | } | 312 | } |
313 | 313 | ||
314 | pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { | 314 | pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { |
@@ -540,7 +540,7 @@ impl HasResolver for ConstId { | |||
540 | 540 | ||
541 | impl HasResolver for StaticId { | 541 | impl 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_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index 8af061116..5f10e9a88 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs | |||
@@ -64,7 +64,7 @@ pub enum TypeBound { | |||
64 | 64 | ||
65 | impl TypeRef { | 65 | impl TypeRef { |
66 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. | 66 | /// Converts an `ast::TypeRef` to a `hir::TypeRef`. |
67 | pub fn from_ast(node: ast::TypeRef) -> Self { | 67 | pub(crate) fn from_ast(node: ast::TypeRef) -> Self { |
68 | match node { | 68 | match node { |
69 | ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()), | 69 | ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()), |
70 | ast::TypeRef::TupleType(inner) => { | 70 | ast::TypeRef::TupleType(inner) => { |
@@ -113,7 +113,7 @@ impl TypeRef { | |||
113 | } | 113 | } |
114 | } | 114 | } |
115 | 115 | ||
116 | pub fn from_ast_opt(node: Option<ast::TypeRef>) -> Self { | 116 | pub(crate) fn from_ast_opt(node: Option<ast::TypeRef>) -> Self { |
117 | if let Some(node) = node { | 117 | if let Some(node) = node { |
118 | TypeRef::from_ast(node) | 118 | TypeRef::from_ast(node) |
119 | } else { | 119 | } else { |
@@ -121,7 +121,7 @@ impl TypeRef { | |||
121 | } | 121 | } |
122 | } | 122 | } |
123 | 123 | ||
124 | pub fn unit() -> TypeRef { | 124 | pub(crate) fn unit() -> TypeRef { |
125 | TypeRef::Tuple(Vec::new()) | 125 | TypeRef::Tuple(Vec::new()) |
126 | } | 126 | } |
127 | } | 127 | } |
@@ -135,7 +135,7 @@ pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) | |||
135 | } | 135 | } |
136 | 136 | ||
137 | impl TypeBound { | 137 | impl TypeBound { |
138 | pub fn from_ast(node: ast::TypeBound) -> Self { | 138 | pub(crate) fn from_ast(node: ast::TypeBound) -> Self { |
139 | match node.kind() { | 139 | match node.kind() { |
140 | ast::TypeBoundKind::PathType(path_type) => { | 140 | ast::TypeBoundKind::PathType(path_type) => { |
141 | let path = match path_type.path() { | 141 | let path = match path_type.path() { |
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 | ||
290 | fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool { | 290 | fn 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 | ||
294 | fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { | 294 | fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { |
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 77f729a25..55ff4d6ef 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -209,6 +209,7 @@ impl ProjectWorkspace { | |||
209 | } | 209 | } |
210 | 210 | ||
211 | let libcore = sysroot.core().and_then(|it| sysroot_crates.get(&it).copied()); | 211 | let libcore = sysroot.core().and_then(|it| sysroot_crates.get(&it).copied()); |
212 | let liballoc = sysroot.alloc().and_then(|it| sysroot_crates.get(&it).copied()); | ||
212 | let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied()); | 213 | let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied()); |
213 | let libproc_macro = | 214 | let libproc_macro = |
214 | sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied()); | 215 | sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied()); |
@@ -278,6 +279,11 @@ impl ProjectWorkspace { | |||
278 | log::error!("cyclic dependency on core for {}", pkg.name(&cargo)) | 279 | log::error!("cyclic dependency on core for {}", pkg.name(&cargo)) |
279 | } | 280 | } |
280 | } | 281 | } |
282 | if let Some(alloc) = liballoc { | ||
283 | if let Err(_) = crate_graph.add_dep(from, "alloc".into(), alloc) { | ||
284 | log::error!("cyclic dependency on alloc for {}", pkg.name(&cargo)) | ||
285 | } | ||
286 | } | ||
281 | if let Some(std) = libstd { | 287 | if let Some(std) = libstd { |
282 | if let Err(_) = crate_graph.add_dep(from, "std".into(), std) { | 288 | if let Err(_) = crate_graph.add_dep(from, "std".into(), std) { |
283 | log::error!("cyclic dependency on std for {}", pkg.name(&cargo)) | 289 | log::error!("cyclic dependency on std for {}", pkg.name(&cargo)) |
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index 8a7757c41..10ca391b6 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs | |||
@@ -31,6 +31,10 @@ impl Sysroot { | |||
31 | self.by_name("core") | 31 | self.by_name("core") |
32 | } | 32 | } |
33 | 33 | ||
34 | pub fn alloc(&self) -> Option<SysrootCrate> { | ||
35 | self.by_name("alloc") | ||
36 | } | ||
37 | |||
34 | pub fn std(&self) -> Option<SysrootCrate> { | 38 | pub fn std(&self) -> Option<SysrootCrate> { |
35 | self.by_name("std") | 39 | self.by_name("std") |
36 | } | 40 | } |