aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/has_source.rs15
-rw-r--r--crates/hir/src/lib.rs20
-rw-r--r--crates/hir/src/semantics/source_to_def.rs8
-rw-r--r--crates/hir_def/src/attr.rs66
-rw-r--r--crates/hir_def/src/import_map.rs18
-rw-r--r--crates/hir_def/src/item_scope.rs2
-rw-r--r--crates/hir_def/src/lib.rs2
-rw-r--r--crates/hir_def/src/nameres.rs12
-rw-r--r--crates/hir_def/src/nameres/collector.rs47
-rw-r--r--crates/hir_def/src/nameres/proc_macro.rs71
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs26
-rw-r--r--crates/hir_expand/src/builtin_derive.rs6
-rw-r--r--crates/hir_expand/src/builtin_macro.rs13
-rw-r--r--crates/hir_expand/src/db.rs14
-rw-r--r--crates/hir_expand/src/eager.rs12
-rw-r--r--crates/hir_expand/src/hygiene.rs12
-rw-r--r--crates/hir_expand/src/lib.rs26
-rw-r--r--crates/hir_ty/src/autoderef.rs5
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs15
-rw-r--r--crates/hir_ty/src/display.rs14
-rw-r--r--crates/hir_ty/src/infer.rs5
-rw-r--r--crates/hir_ty/src/infer/coerce.rs6
-rw-r--r--crates/hir_ty/src/infer/expr.rs13
-rw-r--r--crates/hir_ty/src/infer/path.rs12
-rw-r--r--crates/hir_ty/src/infer/unify.rs4
-rw-r--r--crates/hir_ty/src/lib.rs39
-rw-r--r--crates/hir_ty/src/lower.rs22
-rw-r--r--crates/hir_ty/src/method_resolution.rs5
-rw-r--r--crates/hir_ty/src/traits.rs2
-rw-r--r--crates/hir_ty/src/traits/chalk.rs10
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs15
-rw-r--r--crates/hir_ty/src/utils.rs10
-rw-r--r--crates/ide/src/display/navigation_target.rs8
-rw-r--r--crates/ide/src/goto_definition.rs17
-rw-r--r--crates/ide/src/hover.rs14
-rw-r--r--crates/ide/src/syntax_highlighting.rs16
-rw-r--r--crates/ide/src/syntax_highlighting/html.rs2
-rw-r--r--crates/ide/src/syntax_highlighting/inject.rs66
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs14
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_injection.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_strings.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/injection.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html2
-rw-r--r--crates/ide_completion/src/render/macro_.rs2
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs2
-rw-r--r--crates/rust-analyzer/src/to_proto.rs2
-rw-r--r--docs/user/manual.adoc6
52 files changed, 481 insertions, 237 deletions
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index 262002671..d57fad9ed 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -6,7 +6,7 @@ use hir_def::{
6 src::{HasChildSource, HasSource as _}, 6 src::{HasChildSource, HasSource as _},
7 Lookup, VariantId, 7 Lookup, VariantId,
8}; 8};
9use hir_expand::InFile; 9use hir_expand::{InFile, MacroDefKind};
10use syntax::ast; 10use syntax::ast;
11 11
12use crate::{ 12use crate::{
@@ -111,10 +111,17 @@ impl HasSource for TypeAlias {
111 } 111 }
112} 112}
113impl HasSource for MacroDef { 113impl HasSource for MacroDef {
114 type Ast = ast::Macro; 114 type Ast = Either<ast::Macro, ast::Fn>;
115 fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { 115 fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
116 let ast_id = self.id.ast_id?; 116 Some(match &self.id.kind {
117 Some(InFile { file_id: ast_id.file_id, value: ast_id.to_node(db.upcast()) }) 117 MacroDefKind::Declarative(id)
118 | MacroDefKind::BuiltIn(_, id)
119 | MacroDefKind::BuiltInDerive(_, id)
120 | MacroDefKind::BuiltInEager(_, id) => {
121 id.with_value(Either::Left(id.to_node(db.upcast())))
122 }
123 MacroDefKind::ProcMacro(_, id) => id.map(|_| Either::Right(id.to_node(db.upcast()))),
124 })
118 } 125 }
119} 126}
120impl HasSource for Impl { 127impl HasSource for Impl {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index b41a36a78..67ec8e82a 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1144,17 +1144,21 @@ impl MacroDef {
1144 1144
1145 /// XXX: this parses the file 1145 /// XXX: this parses the file
1146 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 1146 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1147 self.source(db)?.value.name().map(|it| it.as_name()) 1147 match self.source(db)?.value {
1148 Either::Left(it) => it.name().map(|it| it.as_name()),
1149 Either::Right(it) => it.name().map(|it| it.as_name()),
1150 }
1148 } 1151 }
1149 1152
1150 /// Indicate it is a proc-macro 1153 /// Indicate it is a proc-macro
1151 pub fn is_proc_macro(&self) -> bool { 1154 pub fn is_proc_macro(&self) -> bool {
1152 matches!(self.id.kind, MacroDefKind::ProcMacro(_)) 1155 matches!(self.id.kind, MacroDefKind::ProcMacro(..))
1153 } 1156 }
1154 1157
1155 /// Indicate it is a derive macro 1158 /// Indicate it is a derive macro
1156 pub fn is_derive_macro(&self) -> bool { 1159 pub fn is_derive_macro(&self) -> bool {
1157 matches!(self.id.kind, MacroDefKind::ProcMacro(_) | MacroDefKind::BuiltInDerive(_)) 1160 // FIXME: wrong for `ProcMacro`
1161 matches!(self.id.kind, MacroDefKind::ProcMacro(..) | MacroDefKind::BuiltInDerive(..))
1158 } 1162 }
1159} 1163}
1160 1164
@@ -1458,7 +1462,7 @@ impl TypeParam {
1458 .into_iter() 1462 .into_iter()
1459 .filter_map(|pred| match &pred.value { 1463 .filter_map(|pred| match &pred.value {
1460 hir_ty::GenericPredicate::Implemented(trait_ref) => { 1464 hir_ty::GenericPredicate::Implemented(trait_ref) => {
1461 Some(Trait::from(trait_ref.trait_)) 1465 Some(Trait::from(trait_ref.hir_trait_id()))
1462 } 1466 }
1463 _ => None, 1467 _ => None,
1464 }) 1468 })
@@ -1753,8 +1757,8 @@ impl Type {
1753 1757
1754 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { 1758 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1755 let trait_ref = hir_ty::TraitRef { 1759 let trait_ref = hir_ty::TraitRef {
1756 trait_: trait_.id, 1760 trait_id: hir_ty::to_chalk_trait_id(trait_.id),
1757 substs: Substitution::build_for_def(db, trait_.id) 1761 substitution: Substitution::build_for_def(db, trait_.id)
1758 .push(self.ty.value.clone()) 1762 .push(self.ty.value.clone())
1759 .fill(args.iter().map(|t| t.ty.value.clone())) 1763 .fill(args.iter().map(|t| t.ty.value.clone()))
1760 .build(), 1764 .build(),
@@ -2019,7 +2023,7 @@ impl Type {
2019 it.into_iter() 2023 it.into_iter()
2020 .filter_map(|pred| match pred { 2024 .filter_map(|pred| match pred {
2021 hir_ty::GenericPredicate::Implemented(trait_ref) => { 2025 hir_ty::GenericPredicate::Implemented(trait_ref) => {
2022 Some(Trait::from(trait_ref.trait_)) 2026 Some(Trait::from(trait_ref.hir_trait_id()))
2023 } 2027 }
2024 _ => None, 2028 _ => None,
2025 }) 2029 })
@@ -2063,7 +2067,7 @@ impl Type {
2063 match pred { 2067 match pred {
2064 GenericPredicate::Implemented(trait_ref) => { 2068 GenericPredicate::Implemented(trait_ref) => {
2065 cb(type_.clone()); 2069 cb(type_.clone());
2066 walk_substs(db, type_, &trait_ref.substs, cb); 2070 walk_substs(db, type_, &trait_ref.substitution, cb);
2067 } 2071 }
2068 _ => (), 2072 _ => (),
2069 } 2073 }
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index c6ad5ecb5..762809fcd 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -195,12 +195,12 @@ impl SourceToDefCtx<'_, '_> {
195 &mut self, 195 &mut self,
196 src: InFile<ast::MacroRules>, 196 src: InFile<ast::MacroRules>,
197 ) -> Option<MacroDefId> { 197 ) -> Option<MacroDefId> {
198 let kind = MacroDefKind::Declarative; 198 let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value);
199 let ast_id = AstId::new(src.file_id, file_ast_id.upcast());
200 let kind = MacroDefKind::Declarative(ast_id);
199 let file_id = src.file_id.original_file(self.db.upcast()); 201 let file_id = src.file_id.original_file(self.db.upcast());
200 let krate = self.file_to_def(file_id).get(0).copied()?.krate(); 202 let krate = self.file_to_def(file_id).get(0).copied()?.krate();
201 let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); 203 Some(MacroDefId { krate, kind, local_inner: false })
202 let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast()));
203 Some(MacroDefId { krate, ast_id, kind, local_inner: false })
204 } 204 }
205 205
206 pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { 206 pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index e4c84afbf..1cab0e363 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -209,7 +209,7 @@ impl Attrs {
209 }, 209 },
210 AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db), 210 AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db),
211 AttrDefId::MacroDefId(it) => { 211 AttrDefId::MacroDefId(it) => {
212 it.ast_id.map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)) 212 it.ast_id().map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db))
213 } 213 }
214 AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db), 214 AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db),
215 AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db), 215 AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db),
@@ -283,8 +283,51 @@ impl Attrs {
283 /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes. 283 /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes.
284 /// 284 ///
285 /// `owner` must be the original owner of the attributes. 285 /// `owner` must be the original owner of the attributes.
286 pub fn source_map(&self, owner: &dyn ast::AttrsOwner) -> AttrSourceMap { 286 // FIXME: figure out a better api that doesnt require the for_module hack
287 AttrSourceMap { attrs: collect_attrs(owner).collect() } 287 pub fn source_map(&self, owner: InFile<&dyn ast::AttrsOwner>) -> AttrSourceMap {
288 // FIXME: This doesn't work correctly for modules, as the attributes there can have up to
289 // two different owners
290 AttrSourceMap {
291 attrs: collect_attrs(owner.value)
292 .map(|attr| InFile::new(owner.file_id, attr))
293 .collect(),
294 }
295 }
296
297 pub fn source_map_for_module(
298 &self,
299 db: &dyn DefDatabase,
300 module: crate::ModuleId,
301 ) -> AttrSourceMap {
302 let def_map = module.def_map(db);
303 let mod_data = &def_map[module.local_id];
304 let attrs = match mod_data.declaration_source(db) {
305 Some(it) => {
306 let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner)
307 .map(|attr| InFile::new(it.file_id, attr))
308 .collect();
309 if let InFile { file_id, value: ModuleSource::SourceFile(file) } =
310 mod_data.definition_source(db)
311 {
312 attrs.extend(
313 collect_attrs(&file as &dyn ast::AttrsOwner)
314 .map(|attr| InFile::new(file_id, attr)),
315 )
316 }
317 attrs
318 }
319 None => {
320 let InFile { file_id, value } = mod_data.definition_source(db);
321 match &value {
322 ModuleSource::SourceFile(file) => collect_attrs(file as &dyn ast::AttrsOwner),
323 ModuleSource::Module(module) => collect_attrs(module as &dyn ast::AttrsOwner),
324 ModuleSource::BlockExpr(block) => collect_attrs(block as &dyn ast::AttrsOwner),
325 }
326 .map(|attr| InFile::new(file_id, attr))
327 .collect()
328 }
329 };
330 AttrSourceMap { attrs }
288 } 331 }
289 332
290 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { 333 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
@@ -379,7 +422,7 @@ fn inner_attributes(
379} 422}
380 423
381pub struct AttrSourceMap { 424pub struct AttrSourceMap {
382 attrs: Vec<Either<ast::Attr, ast::Comment>>, 425 attrs: Vec<InFile<Either<ast::Attr, ast::Comment>>>,
383} 426}
384 427
385impl AttrSourceMap { 428impl AttrSourceMap {
@@ -389,10 +432,11 @@ impl AttrSourceMap {
389 /// 432 ///
390 /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of 433 /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
391 /// the attribute represented by `Attr`. 434 /// the attribute represented by `Attr`.
392 pub fn source_of(&self, attr: &Attr) -> &Either<ast::Attr, ast::Comment> { 435 pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> {
393 self.attrs 436 self.attrs
394 .get(attr.index as usize) 437 .get(attr.index as usize)
395 .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index)) 438 .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index))
439 .as_ref()
396 } 440 }
397} 441}
398 442
@@ -428,18 +472,6 @@ impl Attr {
428 Some(Attr { index, path, input }) 472 Some(Attr { index, path, input })
429 } 473 }
430 474
431 /// Maps this lowered `Attr` back to its original syntax node.
432 ///
433 /// `owner` must be the original owner of the attribute.
434 ///
435 /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
436 /// the attribute represented by `Attr`.
437 pub fn to_src(&self, owner: &dyn ast::AttrsOwner) -> Either<ast::Attr, ast::Comment> {
438 collect_attrs(owner).nth(self.index as usize).unwrap_or_else(|| {
439 panic!("cannot find `Attr` at index {} in {}", self.index, owner.syntax())
440 })
441 }
442
443 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths 475 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
444 /// to derive macros. 476 /// to derive macros.
445 /// 477 ///
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs
index 369bc3350..960cabb5f 100644
--- a/crates/hir_def/src/import_map.rs
+++ b/crates/hir_def/src/import_map.rs
@@ -912,10 +912,10 @@ mod tests {
912 dep::fmt (t) 912 dep::fmt (t)
913 dep::format (f) 913 dep::format (f)
914 dep::Fmt (v) 914 dep::Fmt (v)
915 dep::fmt::Display (t) 915 dep::Fmt (m)
916 dep::Fmt (t) 916 dep::Fmt (t)
917 dep::fmt::Display::fmt (a) 917 dep::fmt::Display::fmt (a)
918 dep::Fmt (m) 918 dep::fmt::Display (t)
919 "#]], 919 "#]],
920 ); 920 );
921 921
@@ -926,9 +926,9 @@ mod tests {
926 expect![[r#" 926 expect![[r#"
927 dep::fmt (t) 927 dep::fmt (t)
928 dep::Fmt (v) 928 dep::Fmt (v)
929 dep::Fmt (m)
929 dep::Fmt (t) 930 dep::Fmt (t)
930 dep::fmt::Display::fmt (a) 931 dep::fmt::Display::fmt (a)
931 dep::Fmt (m)
932 "#]], 932 "#]],
933 ); 933 );
934 934
@@ -939,10 +939,10 @@ mod tests {
939 expect![[r#" 939 expect![[r#"
940 dep::fmt (t) 940 dep::fmt (t)
941 dep::Fmt (v) 941 dep::Fmt (v)
942 dep::fmt::Display (t) 942 dep::Fmt (m)
943 dep::Fmt (t) 943 dep::Fmt (t)
944 dep::fmt::Display::fmt (a) 944 dep::fmt::Display::fmt (a)
945 dep::Fmt (m) 945 dep::fmt::Display (t)
946 "#]], 946 "#]],
947 ); 947 );
948 } 948 }
@@ -980,10 +980,10 @@ mod tests {
980 expect![[r#" 980 expect![[r#"
981 dep::fmt (t) 981 dep::fmt (t)
982 dep::Fmt (v) 982 dep::Fmt (v)
983 dep::fmt::Display (t) 983 dep::Fmt (m)
984 dep::Fmt (t) 984 dep::Fmt (t)
985 dep::fmt::Display::fmt (a) 985 dep::fmt::Display::fmt (a)
986 dep::Fmt (m) 986 dep::fmt::Display (t)
987 "#]], 987 "#]],
988 ); 988 );
989 989
@@ -994,9 +994,9 @@ mod tests {
994 expect![[r#" 994 expect![[r#"
995 dep::fmt (t) 995 dep::fmt (t)
996 dep::Fmt (v) 996 dep::Fmt (v)
997 dep::Fmt (m)
997 dep::Fmt (t) 998 dep::Fmt (t)
998 dep::fmt::Display::fmt (a) 999 dep::fmt::Display::fmt (a)
999 dep::Fmt (m)
1000 "#]], 1000 "#]],
1001 ); 1001 );
1002 } 1002 }
@@ -1058,8 +1058,8 @@ mod tests {
1058 Query::new("".to_string()).limit(2), 1058 Query::new("".to_string()).limit(2),
1059 expect![[r#" 1059 expect![[r#"
1060 dep::fmt (t) 1060 dep::fmt (t)
1061 dep::Fmt (t)
1062 dep::Fmt (m) 1061 dep::Fmt (m)
1062 dep::Fmt (t)
1063 dep::Fmt (v) 1063 dep::Fmt (v)
1064 "#]], 1064 "#]],
1065 ); 1065 );
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs
index aafd73b60..f3ebe7c72 100644
--- a/crates/hir_def/src/item_scope.rs
+++ b/crates/hir_def/src/item_scope.rs
@@ -252,7 +252,7 @@ impl ItemScope {
252 .for_each(|vis| *vis = Visibility::Module(this_module)); 252 .for_each(|vis| *vis = Visibility::Module(this_module));
253 253
254 for (mac, vis) in self.macros.values_mut() { 254 for (mac, vis) in self.macros.values_mut() {
255 if let MacroDefKind::ProcMacro(_) = mac.kind { 255 if let MacroDefKind::ProcMacro(..) = mac.kind {
256 // FIXME: Technically this is insufficient since reexports of proc macros are also 256 // FIXME: Technically this is insufficient since reexports of proc macros are also
257 // forbidden. Practically nobody does that. 257 // forbidden. Practically nobody does that.
258 continue; 258 continue;
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index 6758411a0..21add086d 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -650,7 +650,7 @@ fn macro_call_as_call_id(
650) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { 650) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
651 let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?; 651 let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?;
652 652
653 let res = if let MacroDefKind::BuiltInEager(_) = def.kind { 653 let res = if let MacroDefKind::BuiltInEager(..) = def.kind {
654 let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast())); 654 let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast()));
655 let hygiene = Hygiene::new(db.upcast(), call.ast_id.file_id); 655 let hygiene = Hygiene::new(db.upcast(), call.ast_id.file_id);
656 656
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index c97be584e..1ac326f97 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -53,11 +53,12 @@ mod path_resolution;
53 53
54#[cfg(test)] 54#[cfg(test)]
55mod tests; 55mod tests;
56mod proc_macro;
56 57
57use std::sync::Arc; 58use std::sync::Arc;
58 59
59use base_db::{CrateId, Edition, FileId}; 60use base_db::{CrateId, Edition, FileId};
60use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; 61use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId};
61use la_arena::Arena; 62use la_arena::Arena;
62use profile::Count; 63use profile::Count;
63use rustc_hash::FxHashMap; 64use rustc_hash::FxHashMap;
@@ -73,6 +74,8 @@ use crate::{
73 AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId, 74 AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId,
74}; 75};
75 76
77use self::proc_macro::ProcMacroDef;
78
76/// Contains the results of (early) name resolution. 79/// Contains the results of (early) name resolution.
77/// 80///
78/// A `DefMap` stores the module tree and the definitions that are in scope in every module after 81/// A `DefMap` stores the module tree and the definitions that are in scope in every module after
@@ -95,6 +98,12 @@ pub struct DefMap {
95 prelude: Option<ModuleId>, 98 prelude: Option<ModuleId>,
96 extern_prelude: FxHashMap<Name, ModuleDefId>, 99 extern_prelude: FxHashMap<Name, ModuleDefId>,
97 100
101 /// Side table with additional proc. macro info, for use by name resolution in downstream
102 /// crates.
103 ///
104 /// (the primary purpose is to resolve derive helpers)
105 exported_proc_macros: FxHashMap<MacroDefId, ProcMacroDef>,
106
98 edition: Edition, 107 edition: Edition,
99 diagnostics: Vec<DefDiagnostic>, 108 diagnostics: Vec<DefDiagnostic>,
100} 109}
@@ -237,6 +246,7 @@ impl DefMap {
237 krate, 246 krate,
238 edition, 247 edition,
239 extern_prelude: FxHashMap::default(), 248 extern_prelude: FxHashMap::default(),
249 exported_proc_macros: FxHashMap::default(),
240 prelude: None, 250 prelude: None,
241 root, 251 root,
242 modules, 252 modules,
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index d0fefb5af..dcedf7766 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -18,7 +18,6 @@ use hir_expand::{
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
20use syntax::ast; 20use syntax::ast;
21use tt::{Leaf, TokenTree};
22 21
23use crate::{ 22use crate::{
24 attr::Attrs, 23 attr::Attrs,
@@ -42,6 +41,8 @@ use crate::{
42 UnresolvedMacro, 41 UnresolvedMacro,
43}; 42};
44 43
44use super::proc_macro::ProcMacroDef;
45
45const GLOB_RECURSION_LIMIT: usize = 100; 46const GLOB_RECURSION_LIMIT: usize = 100;
46const EXPANSION_DEPTH_LIMIT: usize = 128; 47const EXPANSION_DEPTH_LIMIT: usize = 128;
47const FIXED_POINT_LIMIT: usize = 8192; 48const FIXED_POINT_LIMIT: usize = 8192;
@@ -353,24 +354,23 @@ impl DefCollector<'_> {
353 /// use a dummy expander that always errors. This comes with the drawback of macros potentially 354 /// use a dummy expander that always errors. This comes with the drawback of macros potentially
354 /// going out of sync with what the build system sees (since we resolve using VFS state, but 355 /// going out of sync with what the build system sees (since we resolve using VFS state, but
355 /// Cargo builds only on-disk files). We could and probably should add diagnostics for that. 356 /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
356 fn resolve_proc_macro(&mut self, name: &Name) { 357 fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>) {
357 self.exports_proc_macros = true; 358 self.exports_proc_macros = true;
358 let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { 359 let macro_def = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
359 Some((_, expander)) => MacroDefId { 360 Some((_, expander)) => MacroDefId {
360 ast_id: None,
361 krate: self.def_map.krate, 361 krate: self.def_map.krate,
362 kind: MacroDefKind::ProcMacro(*expander), 362 kind: MacroDefKind::ProcMacro(*expander, ast_id),
363 local_inner: false, 363 local_inner: false,
364 }, 364 },
365 None => MacroDefId { 365 None => MacroDefId {
366 ast_id: None,
367 krate: self.def_map.krate, 366 krate: self.def_map.krate,
368 kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), 367 kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate), ast_id),
369 local_inner: false, 368 local_inner: false,
370 }, 369 },
371 }; 370 };
372 371
373 self.define_proc_macro(name.clone(), macro_def); 372 self.define_proc_macro(def.name.clone(), macro_def);
373 self.def_map.exported_proc_macros.insert(macro_def, def);
374 } 374 }
375 375
376 /// Define a macro with `macro_rules`. 376 /// Define a macro with `macro_rules`.
@@ -1118,7 +1118,8 @@ impl ModCollector<'_, '_> {
1118 ModItem::Function(id) => { 1118 ModItem::Function(id) => {
1119 let func = &self.item_tree[id]; 1119 let func = &self.item_tree[id];
1120 1120
1121 self.collect_proc_macro_def(&func.name, &attrs); 1121 let ast_id = InFile::new(self.file_id, func.ast_id);
1122 self.collect_proc_macro_def(&func.name, ast_id, &attrs);
1122 1123
1123 def = Some(DefData { 1124 def = Some(DefData {
1124 id: FunctionLoc { 1125 id: FunctionLoc {
@@ -1385,28 +1386,11 @@ impl ModCollector<'_, '_> {
1385 } 1386 }
1386 1387
1387 /// If `attrs` registers a procedural macro, collects its definition. 1388 /// If `attrs` registers a procedural macro, collects its definition.
1388 fn collect_proc_macro_def(&mut self, func_name: &Name, attrs: &Attrs) { 1389 fn collect_proc_macro_def(&mut self, func_name: &Name, ast_id: AstId<ast::Fn>, attrs: &Attrs) {
1389 // FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere 1390 // FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere
1390 // FIXME: distinguish the type of macro 1391 if let Some(proc_macro) = attrs.parse_proc_macro_decl(func_name) {
1391 let macro_name = if attrs.by_key("proc_macro").exists() 1392 self.def_collector.export_proc_macro(proc_macro, ast_id);
1392 || attrs.by_key("proc_macro_attribute").exists() 1393 }
1393 {
1394 func_name.clone()
1395 } else {
1396 let derive = attrs.by_key("proc_macro_derive");
1397 if let Some(arg) = derive.tt_values().next() {
1398 if let [TokenTree::Leaf(Leaf::Ident(trait_name)), ..] = &*arg.token_trees {
1399 trait_name.as_name()
1400 } else {
1401 log::trace!("malformed `#[proc_macro_derive]`: {}", arg);
1402 return;
1403 }
1404 } else {
1405 return;
1406 }
1407 };
1408
1409 self.def_collector.resolve_proc_macro(&macro_name);
1410 } 1394 }
1411 1395
1412 fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) { 1396 fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
@@ -1445,9 +1429,8 @@ impl ModCollector<'_, '_> {
1445 1429
1446 // Case 2: normal `macro_rules!` macro 1430 // Case 2: normal `macro_rules!` macro
1447 let macro_id = MacroDefId { 1431 let macro_id = MacroDefId {
1448 ast_id: Some(ast_id),
1449 krate: self.def_collector.def_map.krate, 1432 krate: self.def_collector.def_map.krate,
1450 kind: MacroDefKind::Declarative, 1433 kind: MacroDefKind::Declarative(ast_id),
1451 local_inner: is_local_inner, 1434 local_inner: is_local_inner,
1452 }; 1435 };
1453 self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export); 1436 self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export);
diff --git a/crates/hir_def/src/nameres/proc_macro.rs b/crates/hir_def/src/nameres/proc_macro.rs
new file mode 100644
index 000000000..156598f19
--- /dev/null
+++ b/crates/hir_def/src/nameres/proc_macro.rs
@@ -0,0 +1,71 @@
1//! Nameres-specific procedural macro data and helpers.
2
3use hir_expand::name::{AsName, Name};
4use tt::{Leaf, TokenTree};
5
6use crate::attr::Attrs;
7
8#[derive(Debug, PartialEq, Eq)]
9pub(super) struct ProcMacroDef {
10 pub(super) name: Name,
11 pub(super) kind: ProcMacroKind,
12}
13
14#[derive(Debug, PartialEq, Eq)]
15pub(super) enum ProcMacroKind {
16 CustomDerive { helpers: Box<[Name]> },
17 FnLike,
18 Attr,
19}
20
21impl Attrs {
22 #[rustfmt::skip]
23 pub(super) fn parse_proc_macro_decl(&self, func_name: &Name) -> Option<ProcMacroDef> {
24 if self.by_key("proc_macro").exists() {
25 Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::FnLike })
26 } else if self.by_key("proc_macro_attribute").exists() {
27 Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Attr })
28 } else if self.by_key("proc_macro_derive").exists() {
29 let derive = self.by_key("proc_macro_derive").tt_values().next().unwrap();
30
31 match &*derive.token_trees {
32 // `#[proc_macro_derive(Trait)]`
33 [TokenTree::Leaf(Leaf::Ident(trait_name))] => Some(ProcMacroDef {
34 name: trait_name.as_name(),
35 kind: ProcMacroKind::CustomDerive { helpers: Box::new([]) },
36 }),
37
38 // `#[proc_macro_derive(Trait, attibutes(helper1, helper2, ...))]`
39 [
40 TokenTree::Leaf(Leaf::Ident(trait_name)),
41 TokenTree::Leaf(Leaf::Punct(comma)),
42 TokenTree::Leaf(Leaf::Ident(attributes)),
43 TokenTree::Subtree(helpers)
44 ] if comma.char == ',' && attributes.text == "attributes" =>
45 {
46 let helpers = helpers.token_trees.iter()
47 .filter(|tt| !matches!(tt, TokenTree::Leaf(Leaf::Punct(comma)) if comma.char == ','))
48 .map(|tt| {
49 match tt {
50 TokenTree::Leaf(Leaf::Ident(helper)) => Some(helper.as_name()),
51 _ => None
52 }
53 })
54 .collect::<Option<Box<[_]>>>()?;
55
56 Some(ProcMacroDef {
57 name: trait_name.as_name(),
58 kind: ProcMacroKind::CustomDerive { helpers },
59 })
60 }
61
62 _ => {
63 log::trace!("malformed `#[proc_macro_derive]`: {}", derive);
64 None
65 }
66 }
67 } else {
68 None
69 }
70 }
71}
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index f65a655bf..d59d3c0db 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -1,4 +1,5 @@
1use super::*; 1use super::*;
2use crate::nameres::proc_macro::{ProcMacroDef, ProcMacroKind};
2 3
3#[test] 4#[test]
4fn macro_rules_are_globally_visible() { 5fn macro_rules_are_globally_visible() {
@@ -790,3 +791,28 @@ fn proc_macro_censoring() {
790 "#]], 791 "#]],
791 ); 792 );
792} 793}
794
795#[test]
796fn collects_derive_helpers() {
797 let def_map = compute_crate_def_map(
798 r"
799 struct TokenStream;
800
801 #[proc_macro_derive(AnotherTrait, attributes(helper_attr))]
802 pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
803 TokenStream
804 }
805 ",
806 );
807
808 assert_eq!(def_map.exported_proc_macros.len(), 1);
809 match def_map.exported_proc_macros.values().next() {
810 Some(ProcMacroDef { kind: ProcMacroKind::CustomDerive { helpers }, .. }) => {
811 match &**helpers {
812 [attr] => assert_eq!(attr.to_string(), "helper_attr"),
813 _ => unreachable!(),
814 }
815 }
816 _ => unreachable!(),
817 }
818}
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs
index a8d267c30..60fd2ebdd 100644
--- a/crates/hir_expand/src/builtin_derive.rs
+++ b/crates/hir_expand/src/builtin_derive.rs
@@ -61,8 +61,7 @@ pub fn find_builtin_derive(
61 let expander = BuiltinDeriveExpander::find_by_name(ident)?; 61 let expander = BuiltinDeriveExpander::find_by_name(ident)?;
62 Some(MacroDefId { 62 Some(MacroDefId {
63 krate, 63 krate,
64 ast_id: Some(ast_id), 64 kind: MacroDefKind::BuiltInDerive(expander, ast_id),
65 kind: MacroDefKind::BuiltInDerive(expander),
66 local_inner: false, 65 local_inner: false,
67 }) 66 })
68} 67}
@@ -314,8 +313,7 @@ $0
314 let loc = MacroCallLoc { 313 let loc = MacroCallLoc {
315 def: MacroDefId { 314 def: MacroDefId {
316 krate: CrateId(0), 315 krate: CrateId(0),
317 ast_id: Some(macro_ast_id), 316 kind: MacroDefKind::BuiltInDerive(expander, macro_ast_id),
318 kind: MacroDefKind::BuiltInDerive(expander),
319 local_inner: false, 317 local_inner: false,
320 }, 318 },
321 krate: CrateId(0), 319 krate: CrateId(0),
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index fce09a9e7..8529b43b6 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -71,14 +71,12 @@ pub fn find_builtin_macro(
71 match kind { 71 match kind {
72 Either::Left(kind) => Some(MacroDefId { 72 Either::Left(kind) => Some(MacroDefId {
73 krate, 73 krate,
74 ast_id: Some(ast_id), 74 kind: MacroDefKind::BuiltIn(kind, ast_id),
75 kind: MacroDefKind::BuiltIn(kind),
76 local_inner: false, 75 local_inner: false,
77 }), 76 }),
78 Either::Right(kind) => Some(MacroDefId { 77 Either::Right(kind) => Some(MacroDefId {
79 krate, 78 krate,
80 ast_id: Some(ast_id), 79 kind: MacroDefKind::BuiltInEager(kind, ast_id),
81 kind: MacroDefKind::BuiltInEager(kind),
82 local_inner: false, 80 local_inner: false,
83 }), 81 }),
84 } 82 }
@@ -512,6 +510,7 @@ mod tests {
512 let macro_call = macro_calls.pop().unwrap(); 510 let macro_call = macro_calls.pop().unwrap();
513 511
514 let expander = find_by_name(&macro_rules.name().unwrap().as_name()).unwrap(); 512 let expander = find_by_name(&macro_rules.name().unwrap().as_name()).unwrap();
513 let ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules));
515 514
516 let krate = CrateId(0); 515 let krate = CrateId(0);
517 let file_id = match expander { 516 let file_id = match expander {
@@ -519,8 +518,7 @@ mod tests {
519 // the first one should be a macro_rules 518 // the first one should be a macro_rules
520 let def = MacroDefId { 519 let def = MacroDefId {
521 krate: CrateId(0), 520 krate: CrateId(0),
522 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules))), 521 kind: MacroDefKind::BuiltIn(expander, ast_id),
523 kind: MacroDefKind::BuiltIn(expander),
524 local_inner: false, 522 local_inner: false,
525 }; 523 };
526 524
@@ -540,8 +538,7 @@ mod tests {
540 // the first one should be a macro_rules 538 // the first one should be a macro_rules
541 let def = MacroDefId { 539 let def = MacroDefId {
542 krate, 540 krate,
543 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules))), 541 kind: MacroDefKind::BuiltInEager(expander, ast_id),
544 kind: MacroDefKind::BuiltInEager(expander),
545 local_inner: false, 542 local_inner: false,
546 }; 543 };
547 544
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index a3070f1f9..2748e25cf 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -130,8 +130,8 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
130 130
131fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { 131fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
132 match id.kind { 132 match id.kind {
133 MacroDefKind::Declarative => { 133 MacroDefKind::Declarative(ast_id) => {
134 let macro_rules = match id.ast_id?.to_node(db) { 134 let macro_rules = match ast_id.to_node(db) {
135 syntax::ast::Macro::MacroRules(mac) => mac, 135 syntax::ast::Macro::MacroRules(mac) => mac,
136 syntax::ast::Macro::MacroDef(_) => return None, 136 syntax::ast::Macro::MacroDef(_) => return None,
137 }; 137 };
@@ -150,14 +150,14 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander,
150 }; 150 };
151 Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) 151 Some(Arc::new((TokenExpander::MacroRules(rules), tmap)))
152 } 152 }
153 MacroDefKind::BuiltIn(expander) => { 153 MacroDefKind::BuiltIn(expander, _) => {
154 Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default()))) 154 Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default())))
155 } 155 }
156 MacroDefKind::BuiltInDerive(expander) => { 156 MacroDefKind::BuiltInDerive(expander, _) => {
157 Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default()))) 157 Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default())))
158 } 158 }
159 MacroDefKind::BuiltInEager(_) => None, 159 MacroDefKind::BuiltInEager(..) => None,
160 MacroDefKind::ProcMacro(expander) => { 160 MacroDefKind::ProcMacro(expander, ..) => {
161 Some(Arc::new((TokenExpander::ProcMacro(expander), mbe::TokenMap::default()))) 161 Some(Arc::new((TokenExpander::ProcMacro(expander), mbe::TokenMap::default())))
162 } 162 }
163 } 163 }
@@ -269,7 +269,7 @@ fn expand_proc_macro(
269 }; 269 };
270 270
271 let expander = match loc.def.kind { 271 let expander = match loc.def.kind {
272 MacroDefKind::ProcMacro(expander) => expander, 272 MacroDefKind::ProcMacro(expander, ..) => expander,
273 _ => unreachable!(), 273 _ => unreachable!(),
274 }; 274 };
275 275
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index dc618a9ee..04f374a29 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -140,7 +140,7 @@ pub fn expand_eager_macro(
140 let subtree = 140 let subtree =
141 diagnostic_sink.option(to_subtree(&result), || err("failed to parse macro result"))?; 141 diagnostic_sink.option(to_subtree(&result), || err("failed to parse macro result"))?;
142 142
143 if let MacroDefKind::BuiltInEager(eager) = def.kind { 143 if let MacroDefKind::BuiltInEager(eager, _) = def.kind {
144 let res = eager.expand(db, arg_id, &subtree); 144 let res = eager.expand(db, arg_id, &subtree);
145 145
146 let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?; 146 let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?;
@@ -193,7 +193,7 @@ fn eager_macro_recur(
193 let def = diagnostic_sink 193 let def = diagnostic_sink
194 .option_with(|| macro_resolver(child.path()?), || err("failed to resolve macro"))?; 194 .option_with(|| macro_resolver(child.path()?), || err("failed to resolve macro"))?;
195 let insert = match def.kind { 195 let insert = match def.kind {
196 MacroDefKind::BuiltInEager(_) => { 196 MacroDefKind::BuiltInEager(..) => {
197 let id: MacroCallId = expand_eager_macro( 197 let id: MacroCallId = expand_eager_macro(
198 db, 198 db,
199 krate, 199 krate,
@@ -206,10 +206,10 @@ fn eager_macro_recur(
206 db.parse_or_expand(id.as_file()) 206 db.parse_or_expand(id.as_file())
207 .expect("successful macro expansion should be parseable") 207 .expect("successful macro expansion should be parseable")
208 } 208 }
209 MacroDefKind::Declarative 209 MacroDefKind::Declarative(_)
210 | MacroDefKind::BuiltIn(_) 210 | MacroDefKind::BuiltIn(..)
211 | MacroDefKind::BuiltInDerive(_) 211 | MacroDefKind::BuiltInDerive(..)
212 | MacroDefKind::ProcMacro(_) => { 212 | MacroDefKind::ProcMacro(..) => {
213 let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate); 213 let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate);
214 let val = diagnostic_sink.expand_result_option(res)?; 214 let val = diagnostic_sink.expand_result_option(res)?;
215 215
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs
index 87cad326d..20cda1683 100644
--- a/crates/hir_expand/src/hygiene.rs
+++ b/crates/hir_expand/src/hygiene.rs
@@ -145,7 +145,7 @@ fn make_hygiene_info(
145) -> Option<HygieneInfo> { 145) -> Option<HygieneInfo> {
146 let arg_tt = loc.kind.arg(db)?; 146 let arg_tt = loc.kind.arg(db)?;
147 147
148 let def_offset = loc.def.ast_id.and_then(|id| { 148 let def_offset = loc.def.ast_id().and_then(|id| {
149 let def_tt = match id.to_node(db) { 149 let def_tt = match id.to_node(db) {
150 ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(), 150 ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(),
151 ast::Macro::MacroDef(_) => return None, 151 ast::Macro::MacroDef(_) => return None,
@@ -176,13 +176,13 @@ impl HygieneFrame {
176 let loc = db.lookup_intern_macro(id); 176 let loc = db.lookup_intern_macro(id);
177 let info = make_hygiene_info(db, macro_file, &loc); 177 let info = make_hygiene_info(db, macro_file, &loc);
178 match loc.def.kind { 178 match loc.def.kind {
179 MacroDefKind::Declarative => { 179 MacroDefKind::Declarative(_) => {
180 (info, Some(loc.def.krate), loc.def.local_inner) 180 (info, Some(loc.def.krate), loc.def.local_inner)
181 } 181 }
182 MacroDefKind::BuiltIn(_) => (info, Some(loc.def.krate), false), 182 MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false),
183 MacroDefKind::BuiltInDerive(_) => (info, None, false), 183 MacroDefKind::BuiltInDerive(..) => (info, None, false),
184 MacroDefKind::BuiltInEager(_) => (info, None, false), 184 MacroDefKind::BuiltInEager(..) => (info, None, false),
185 MacroDefKind::ProcMacro(_) => (info, None, false), 185 MacroDefKind::ProcMacro(..) => (info, None, false),
186 } 186 }
187 } 187 }
188 }, 188 },
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 7532d00b8..0a379651f 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -143,7 +143,7 @@ impl HirFileId {
143 143
144 let arg_tt = loc.kind.arg(db)?; 144 let arg_tt = loc.kind.arg(db)?;
145 145
146 let def = loc.def.ast_id.and_then(|id| { 146 let def = loc.def.ast_id().and_then(|id| {
147 let def_tt = match id.to_node(db) { 147 let def_tt = match id.to_node(db) {
148 ast::Macro::MacroRules(mac) => mac.token_tree()?, 148 ast::Macro::MacroRules(mac) => mac.token_tree()?,
149 ast::Macro::MacroDef(_) => return None, 149 ast::Macro::MacroDef(_) => return None,
@@ -180,7 +180,7 @@ impl HirFileId {
180 }; 180 };
181 let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id); 181 let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id);
182 let item = match loc.def.kind { 182 let item = match loc.def.kind {
183 MacroDefKind::BuiltInDerive(_) => loc.kind.node(db), 183 MacroDefKind::BuiltInDerive(..) => loc.kind.node(db),
184 _ => return None, 184 _ => return None,
185 }; 185 };
186 Some(item.with_value(ast::Item::cast(item.value.clone())?)) 186 Some(item.with_value(ast::Item::cast(item.value.clone())?))
@@ -224,7 +224,6 @@ impl From<EagerMacroId> for MacroCallId {
224#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 224#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
225pub struct MacroDefId { 225pub struct MacroDefId {
226 pub krate: CrateId, 226 pub krate: CrateId,
227 pub ast_id: Option<AstId<ast::Macro>>,
228 pub kind: MacroDefKind, 227 pub kind: MacroDefKind,
229 228
230 pub local_inner: bool, 229 pub local_inner: bool,
@@ -239,16 +238,27 @@ impl MacroDefId {
239 ) -> LazyMacroId { 238 ) -> LazyMacroId {
240 db.intern_macro(MacroCallLoc { def: self, krate, kind }) 239 db.intern_macro(MacroCallLoc { def: self, krate, kind })
241 } 240 }
241
242 pub fn ast_id(&self) -> Option<AstId<ast::Macro>> {
243 let id = match &self.kind {
244 MacroDefKind::Declarative(id) => id,
245 MacroDefKind::BuiltIn(_, id) => id,
246 MacroDefKind::BuiltInDerive(_, id) => id,
247 MacroDefKind::BuiltInEager(_, id) => id,
248 MacroDefKind::ProcMacro(..) => return None,
249 };
250 Some(*id)
251 }
242} 252}
243 253
244#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 254#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
245pub enum MacroDefKind { 255pub enum MacroDefKind {
246 Declarative, 256 Declarative(AstId<ast::Macro>),
247 BuiltIn(BuiltinFnLikeExpander), 257 BuiltIn(BuiltinFnLikeExpander, AstId<ast::Macro>),
248 // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander 258 // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander
249 BuiltInDerive(BuiltinDeriveExpander), 259 BuiltInDerive(BuiltinDeriveExpander, AstId<ast::Macro>),
250 BuiltInEager(EagerExpander), 260 BuiltInEager(EagerExpander, AstId<ast::Macro>),
251 ProcMacro(ProcMacroExpander), 261 ProcMacro(ProcMacroExpander, AstId<ast::Fn>),
252} 262}
253 263
254#[derive(Debug, Clone, PartialEq, Eq, Hash)] 264#[derive(Debug, Clone, PartialEq, Eq, Hash)]
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index bd2ff5d38..ad4e6f23b 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -12,7 +12,7 @@ use log::{info, warn};
12 12
13use crate::{ 13use crate::{
14 db::HirDatabase, 14 db::HirDatabase,
15 to_assoc_type_id, 15 to_assoc_type_id, to_chalk_trait_id,
16 traits::{InEnvironment, Solution}, 16 traits::{InEnvironment, Solution},
17 utils::generics, 17 utils::generics,
18 BoundVar, Canonical, DebruijnIndex, Interner, Obligation, Substitution, TraitRef, Ty, TyKind, 18 BoundVar, Canonical, DebruijnIndex, Interner, Obligation, Substitution, TraitRef, Ty, TyKind,
@@ -68,7 +68,8 @@ fn deref_by_trait(
68 Substitution::build_for_generics(&generic_params).push(ty.value.value.clone()).build(); 68 Substitution::build_for_generics(&generic_params).push(ty.value.value.clone()).build();
69 69
70 // Check that the type implements Deref at all 70 // Check that the type implements Deref at all
71 let trait_ref = TraitRef { trait_: deref_trait, substs: parameters.clone() }; 71 let trait_ref =
72 TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() };
72 let implements_goal = Canonical { 73 let implements_goal = Canonical {
73 kinds: ty.value.kinds.clone(), 74 kinds: ty.value.kinds.clone(),
74 value: InEnvironment { 75 value: InEnvironment {
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index bfe239793..33a0f4d7d 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -102,7 +102,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
102 let db = self.db; 102 let db = self.db;
103 for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { 103 for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
104 for (_, module) in block_def_map.modules() { 104 for (_, module) in block_def_map.modules() {
105 for (def_id, _) in module.scope.values() { 105 for def_id in module.scope.declarations() {
106 let mut validator = DeclValidator::new(self.db, self.krate, self.sink); 106 let mut validator = DeclValidator::new(self.db, self.krate, self.sink);
107 validator.validate_item(def_id); 107 validator.validate_item(def_id);
108 } 108 }
@@ -902,4 +902,17 @@ extern {
902 "#, 902 "#,
903 ); 903 );
904 } 904 }
905
906 #[test]
907 fn infinite_loop_inner_items() {
908 check_diagnostics(
909 r#"
910fn qualify() {
911 mod foo {
912 use super::*;
913 }
914}
915 "#,
916 )
917 }
905} 918}
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 7ce0f864c..c6b4f37e5 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -344,7 +344,7 @@ impl HirDisplay for Ty {
344 }; 344 };
345 345
346 if let [GenericPredicate::Implemented(trait_ref), _] = predicates.as_ref() { 346 if let [GenericPredicate::Implemented(trait_ref), _] = predicates.as_ref() {
347 let trait_ = trait_ref.trait_; 347 let trait_ = trait_ref.hir_trait_id();
348 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) { 348 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) {
349 return write!(f, "{}", ty_display); 349 return write!(f, "{}", ty_display);
350 } 350 }
@@ -670,7 +670,7 @@ fn write_bounds_like_dyn_trait(
670 for p in predicates.iter() { 670 for p in predicates.iter() {
671 match p { 671 match p {
672 GenericPredicate::Implemented(trait_ref) => { 672 GenericPredicate::Implemented(trait_ref) => {
673 let trait_ = trait_ref.trait_; 673 let trait_ = trait_ref.hir_trait_id();
674 if !is_fn_trait { 674 if !is_fn_trait {
675 is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_); 675 is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_);
676 } 676 }
@@ -685,7 +685,7 @@ fn write_bounds_like_dyn_trait(
685 // existential) here, which is the only thing that's 685 // existential) here, which is the only thing that's
686 // possible in actual Rust, and hence don't print it 686 // possible in actual Rust, and hence don't print it
687 write!(f, "{}", f.db.trait_data(trait_).name)?; 687 write!(f, "{}", f.db.trait_data(trait_).name)?;
688 if let [_, params @ ..] = &*trait_ref.substs.0 { 688 if let [_, params @ ..] = &*trait_ref.substitution.0 {
689 if is_fn_trait { 689 if is_fn_trait {
690 if let Some(args) = params.first().and_then(|it| it.as_tuple()) { 690 if let Some(args) = params.first().and_then(|it| it.as_tuple()) {
691 write!(f, "(")?; 691 write!(f, "(")?;
@@ -745,16 +745,16 @@ impl TraitRef {
745 return write!(f, "{}", TYPE_HINT_TRUNCATION); 745 return write!(f, "{}", TYPE_HINT_TRUNCATION);
746 } 746 }
747 747
748 self.substs[0].hir_fmt(f)?; 748 self.substitution[0].hir_fmt(f)?;
749 if use_as { 749 if use_as {
750 write!(f, " as ")?; 750 write!(f, " as ")?;
751 } else { 751 } else {
752 write!(f, ": ")?; 752 write!(f, ": ")?;
753 } 753 }
754 write!(f, "{}", f.db.trait_data(self.trait_).name)?; 754 write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?;
755 if self.substs.len() > 1 { 755 if self.substitution.len() > 1 {
756 write!(f, "<")?; 756 write!(f, "<")?;
757 f.write_joined(&self.substs[1..], ", ")?; 757 f.write_joined(&self.substitution[1..], ", ")?;
758 write!(f, ">")?; 758 write!(f, ">")?;
759 } 759 }
760 Ok(()) 760 Ok(())
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 2610c9279..b6ae4fc65 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -42,7 +42,7 @@ use super::{
42}; 42};
43use crate::{ 43use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
45 to_assoc_type_id, AliasTy, Interner, TyKind, 45 to_assoc_type_id, to_chalk_trait_id, AliasTy, Interner, TyKind,
46}; 46};
47 47
48pub(crate) use unify::unify; 48pub(crate) use unify::unify;
@@ -394,7 +394,8 @@ impl<'a> InferenceContext<'a> {
394 .push(inner_ty) 394 .push(inner_ty)
395 .fill(params.iter().cloned()) 395 .fill(params.iter().cloned())
396 .build(); 396 .build();
397 let trait_ref = TraitRef { trait_, substs: substs.clone() }; 397 let trait_ref =
398 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() };
398 let projection = ProjectionPredicate { 399 let projection = ProjectionPredicate {
399 ty: ty.clone(), 400 ty: ty.clone(),
400 projection_ty: ProjectionTy { 401 projection_ty: ProjectionTy {
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index b1f98c507..b86474ed4 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -8,7 +8,8 @@ use chalk_ir::{Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9 9
10use crate::{ 10use crate::{
11 autoderef, traits::Solution, Interner, Obligation, Substitution, TraitRef, Ty, TyKind, 11 autoderef, to_chalk_trait_id, traits::Solution, Interner, Obligation, Substitution, TraitRef,
12 Ty, TyKind,
12}; 13};
13 14
14use super::{InEnvironment, InferenceContext}; 15use super::{InEnvironment, InferenceContext};
@@ -140,7 +141,8 @@ impl<'a> InferenceContext<'a> {
140 .push(from_ty.clone()) 141 .push(from_ty.clone())
141 .push(to_ty.clone()) 142 .push(to_ty.clone())
142 .build(); 143 .build();
143 let trait_ref = TraitRef { trait_: coerce_unsized_trait, substs }; 144 let trait_ref =
145 TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs };
144 let goal = InEnvironment::new(self.trait_env.clone(), Obligation::Trait(trait_ref)); 146 let goal = InEnvironment::new(self.trait_env.clone(), Obligation::Trait(trait_ref));
145 147
146 let canonicalizer = self.canonicalizer(); 148 let canonicalizer = self.canonicalizer();
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 0be8c5a90..93548b6c0 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -18,7 +18,7 @@ use crate::{
18 lower::lower_to_chalk_mutability, 18 lower::lower_to_chalk_mutability,
19 method_resolution, op, 19 method_resolution, op,
20 primitive::{self, UintTy}, 20 primitive::{self, UintTy},
21 to_assoc_type_id, 21 to_assoc_type_id, to_chalk_trait_id,
22 traits::{chalk::from_chalk, FnTrait, InEnvironment}, 22 traits::{chalk::from_chalk, FnTrait, InEnvironment},
23 utils::{generics, variant_data, Generics}, 23 utils::{generics, variant_data, Generics},
24 AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, Rawness, Scalar, 24 AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, Rawness, Scalar,
@@ -90,8 +90,10 @@ impl<'a> InferenceContext<'a> {
90 Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); 90 Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
91 91
92 let trait_env = Arc::clone(&self.trait_env); 92 let trait_env = Arc::clone(&self.trait_env);
93 let implements_fn_trait = 93 let implements_fn_trait = Obligation::Trait(TraitRef {
94 Obligation::Trait(TraitRef { trait_: fn_once_trait, substs: substs.clone() }); 94 trait_id: to_chalk_trait_id(fn_once_trait),
95 substitution: substs.clone(),
96 });
95 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { 97 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
96 value: implements_fn_trait.clone(), 98 value: implements_fn_trait.clone(),
97 environment: trait_env, 99 environment: trait_env,
@@ -948,7 +950,10 @@ impl<'a> InferenceContext<'a> {
948 // construct a TraitDef 950 // construct a TraitDef
949 let substs = 951 let substs =
950 parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); 952 parameters.prefix(generics(self.db.upcast(), trait_.into()).len());
951 self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); 953 self.obligations.push(Obligation::Trait(TraitRef {
954 trait_id: to_chalk_trait_id(trait_),
955 substitution: substs,
956 }));
952 } 957 }
953 } 958 }
954 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} 959 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index ea01d6238..e15135fc1 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -9,7 +9,9 @@ use hir_def::{
9}; 9};
10use hir_expand::name::Name; 10use hir_expand::name::Name;
11 11
12use crate::{method_resolution, Interner, Substitution, Ty, TyKind, ValueTyDefId}; 12use crate::{
13 method_resolution, to_chalk_trait_id, Interner, Substitution, Ty, TyKind, ValueTyDefId,
14};
13 15
14use super::{ExprOrPatId, InferenceContext, TraitRef}; 16use super::{ExprOrPatId, InferenceContext, TraitRef};
15 17
@@ -165,7 +167,7 @@ impl<'a> InferenceContext<'a> {
165 segment: PathSegment<'_>, 167 segment: PathSegment<'_>,
166 id: ExprOrPatId, 168 id: ExprOrPatId,
167 ) -> Option<(ValueNs, Option<Substitution>)> { 169 ) -> Option<(ValueNs, Option<Substitution>)> {
168 let trait_ = trait_ref.trait_; 170 let trait_ = trait_ref.hir_trait_id();
169 let item = 171 let item =
170 self.db.trait_data(trait_).items.iter().map(|(_name, id)| (*id)).find_map(|item| { 172 self.db.trait_data(trait_).items.iter().map(|(_name, id)| (*id)).find_map(|item| {
171 match item { 173 match item {
@@ -200,7 +202,7 @@ impl<'a> InferenceContext<'a> {
200 }; 202 };
201 203
202 self.write_assoc_resolution(id, item); 204 self.write_assoc_resolution(id, item);
203 Some((def, Some(trait_ref.substs))) 205 Some((def, Some(trait_ref.substitution)))
204 } 206 }
205 207
206 fn resolve_ty_assoc_item( 208 fn resolve_ty_assoc_item(
@@ -255,8 +257,8 @@ impl<'a> InferenceContext<'a> {
255 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 257 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
256 .build(); 258 .build();
257 self.obligations.push(super::Obligation::Trait(TraitRef { 259 self.obligations.push(super::Obligation::Trait(TraitRef {
258 trait_, 260 trait_id: to_chalk_trait_id(trait_),
259 substs: trait_substs.clone(), 261 substitution: trait_substs.clone(),
260 })); 262 }));
261 Some(trait_substs) 263 Some(trait_substs)
262 } 264 }
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index b2d4f67b3..f5ea09698 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -390,9 +390,9 @@ impl InferenceTable {
390 ) -> bool { 390 ) -> bool {
391 match (pred1, pred2) { 391 match (pred1, pred2) {
392 (GenericPredicate::Implemented(tr1), GenericPredicate::Implemented(tr2)) 392 (GenericPredicate::Implemented(tr1), GenericPredicate::Implemented(tr2))
393 if tr1.trait_ == tr2.trait_ => 393 if tr1.trait_id == tr2.trait_id =>
394 { 394 {
395 self.unify_substs(&tr1.substs, &tr2.substs, depth + 1) 395 self.unify_substs(&tr1.substitution, &tr2.substitution, depth + 1)
396 } 396 }
397 (GenericPredicate::Projection(proj1), GenericPredicate::Projection(proj2)) 397 (GenericPredicate::Projection(proj1), GenericPredicate::Projection(proj2))
398 if proj1.projection_ty.associated_ty_id == proj2.projection_ty.associated_ty_id => 398 if proj1.projection_ty.associated_ty_id == proj2.projection_ty.associated_ty_id =>
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 52b498ff7..3859dbfa1 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -58,6 +58,8 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>;
58pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 58pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
59pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; 59pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
60 60
61pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
62
61#[derive(Clone, PartialEq, Eq, Debug, Hash)] 63#[derive(Clone, PartialEq, Eq, Debug, Hash)]
62pub enum Lifetime { 64pub enum Lifetime {
63 Parameter(LifetimeParamId), 65 Parameter(LifetimeParamId),
@@ -81,7 +83,10 @@ pub struct ProjectionTy {
81 83
82impl ProjectionTy { 84impl ProjectionTy {
83 pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { 85 pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
84 TraitRef { trait_: self.trait_(db), substs: self.substitution.clone() } 86 TraitRef {
87 trait_id: to_chalk_trait_id(self.trait_(db)),
88 substitution: self.substitution.clone(),
89 }
85 } 90 }
86 91
87 fn trait_(&self, db: &dyn HirDatabase) -> TraitId { 92 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
@@ -493,23 +498,25 @@ impl<T: TypeWalk> TypeWalk for Binders<T> {
493} 498}
494 499
495/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. 500/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
496/// Name to be bikeshedded: TraitBound? TraitImplements?
497#[derive(Clone, PartialEq, Eq, Debug, Hash)] 501#[derive(Clone, PartialEq, Eq, Debug, Hash)]
498pub struct TraitRef { 502pub struct TraitRef {
499 /// FIXME name? 503 pub trait_id: ChalkTraitId,
500 pub trait_: TraitId, 504 pub substitution: Substitution,
501 pub substs: Substitution,
502} 505}
503 506
504impl TraitRef { 507impl TraitRef {
505 pub fn self_ty(&self) -> &Ty { 508 pub fn self_type_parameter(&self) -> &Ty {
506 &self.substs[0] 509 &self.substitution[0]
510 }
511
512 pub fn hir_trait_id(&self) -> TraitId {
513 from_chalk_trait_id(self.trait_id)
507 } 514 }
508} 515}
509 516
510impl TypeWalk for TraitRef { 517impl TypeWalk for TraitRef {
511 fn walk(&self, f: &mut impl FnMut(&Ty)) { 518 fn walk(&self, f: &mut impl FnMut(&Ty)) {
512 self.substs.walk(f); 519 self.substitution.walk(f);
513 } 520 }
514 521
515 fn walk_mut_binders( 522 fn walk_mut_binders(
@@ -517,7 +524,7 @@ impl TypeWalk for TraitRef {
517 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 524 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
518 binders: DebruijnIndex, 525 binders: DebruijnIndex,
519 ) { 526 ) {
520 self.substs.walk_mut_binders(f, binders); 527 self.substitution.walk_mut_binders(f, binders);
521 } 528 }
522} 529}
523 530
@@ -784,7 +791,7 @@ impl Ty {
784 791
785 /// If this is a `dyn Trait`, returns that trait. 792 /// If this is a `dyn Trait`, returns that trait.
786 pub fn dyn_trait(&self) -> Option<TraitId> { 793 pub fn dyn_trait(&self) -> Option<TraitId> {
787 self.dyn_trait_ref().map(|it| it.trait_) 794 self.dyn_trait_ref().map(|it| it.trait_id).map(from_chalk_trait_id)
788 } 795 }
789 796
790 fn builtin_deref(&self) -> Option<Ty> { 797 fn builtin_deref(&self) -> Option<Ty> {
@@ -868,8 +875,8 @@ impl Ty {
868 // Parameters will be walked outside, and projection predicate is not used. 875 // Parameters will be walked outside, and projection predicate is not used.
869 // So just provide the Future trait. 876 // So just provide the Future trait.
870 let impl_bound = GenericPredicate::Implemented(TraitRef { 877 let impl_bound = GenericPredicate::Implemented(TraitRef {
871 trait_: future_trait, 878 trait_id: to_chalk_trait_id(future_trait),
872 substs: Substitution::empty(), 879 substitution: Substitution::empty(),
873 }); 880 });
874 Some(vec![impl_bound]) 881 Some(vec![impl_bound])
875 } else { 882 } else {
@@ -1158,3 +1165,11 @@ pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderI
1158 idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(), 1165 idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
1159 } 1166 }
1160} 1167}
1168
1169pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
1170 chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
1171}
1172
1173pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId {
1174 salsa::InternKey::from_intern_id(id.0)
1175}
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 462882b2b..5d950a017 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -27,7 +27,7 @@ use stdx::impl_from;
27 27
28use crate::{ 28use crate::{
29 db::HirDatabase, 29 db::HirDatabase,
30 to_assoc_type_id, to_placeholder_idx, 30 to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
31 traits::chalk::{Interner, ToChalk}, 31 traits::chalk::{Interner, ToChalk},
32 utils::{ 32 utils::{
33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, 33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
@@ -360,7 +360,7 @@ impl<'a> TyLoweringContext<'a> {
360 // FIXME handle type parameters on the segment 360 // FIXME handle type parameters on the segment
361 TyKind::Alias(AliasTy::Projection(ProjectionTy { 361 TyKind::Alias(AliasTy::Projection(ProjectionTy {
362 associated_ty_id: to_assoc_type_id(associated_ty), 362 associated_ty_id: to_assoc_type_id(associated_ty),
363 substitution: super_trait_ref.substs, 363 substitution: super_trait_ref.substitution,
364 })) 364 }))
365 .intern(&Interner) 365 .intern(&Interner)
366 } 366 }
@@ -470,9 +470,9 @@ impl<'a> TyLoweringContext<'a> {
470 "there should be generics if there's a generic param", 470 "there should be generics if there's a generic param",
471 ), 471 ),
472 ); 472 );
473 t.substs.clone().subst_bound_vars(&s) 473 t.substitution.clone().subst_bound_vars(&s)
474 } 474 }
475 TypeParamLoweringMode::Variable => t.substs.clone(), 475 TypeParamLoweringMode::Variable => t.substitution.clone(),
476 }; 476 };
477 // We need to shift in the bound vars, since 477 // We need to shift in the bound vars, since
478 // associated_type_shorthand_candidates does not do that 478 // associated_type_shorthand_candidates does not do that
@@ -641,7 +641,7 @@ impl<'a> TyLoweringContext<'a> {
641 if let Some(self_ty) = explicit_self_ty { 641 if let Some(self_ty) = explicit_self_ty {
642 substs.0[0] = self_ty; 642 substs.0[0] = self_ty;
643 } 643 }
644 TraitRef { trait_: resolved, substs } 644 TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs }
645 } 645 }
646 646
647 fn lower_trait_ref( 647 fn lower_trait_ref(
@@ -743,7 +743,7 @@ impl<'a> TyLoweringContext<'a> {
743 }; 743 };
744 let projection_ty = ProjectionTy { 744 let projection_ty = ProjectionTy {
745 associated_ty_id: to_assoc_type_id(associated_ty), 745 associated_ty_id: to_assoc_type_id(associated_ty),
746 substitution: super_trait_ref.substs, 746 substitution: super_trait_ref.substitution,
747 }; 747 };
748 let mut preds = SmallVec::with_capacity( 748 let mut preds = SmallVec::with_capacity(
749 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), 749 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
@@ -820,8 +820,8 @@ pub fn associated_type_shorthand_candidates<R>(
820 == TypeParamProvenance::TraitSelf 820 == TypeParamProvenance::TraitSelf
821 { 821 {
822 let trait_ref = TraitRef { 822 let trait_ref = TraitRef {
823 trait_: trait_id, 823 trait_id: to_chalk_trait_id(trait_id),
824 substs: Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST), 824 substitution: Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST),
825 }; 825 };
826 traits_.push(trait_ref); 826 traits_.push(trait_ref);
827 } 827 }
@@ -832,7 +832,7 @@ pub fn associated_type_shorthand_candidates<R>(
832 }; 832 };
833 833
834 for t in traits_from_env.into_iter().flat_map(move |t| all_super_trait_refs(db, t)) { 834 for t in traits_from_env.into_iter().flat_map(move |t| all_super_trait_refs(db, t)) {
835 let data = db.trait_data(t.trait_); 835 let data = db.trait_data(t.hir_trait_id());
836 836
837 for (name, assoc_id) in &data.items { 837 for (name, assoc_id) in &data.items {
838 match assoc_id { 838 match assoc_id {
@@ -926,7 +926,7 @@ pub(crate) fn trait_environment_query(
926 continue; 926 continue;
927 } 927 }
928 if let GenericPredicate::Implemented(tr) = &pred { 928 if let GenericPredicate::Implemented(tr) = &pred {
929 traits_in_scope.push((tr.self_ty().clone(), tr.trait_)); 929 traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id()));
930 } 930 }
931 let program_clause: chalk_ir::ProgramClause<Interner> = 931 let program_clause: chalk_ir::ProgramClause<Interner> =
932 pred.clone().to_chalk(db).cast(&Interner); 932 pred.clone().to_chalk(db).cast(&Interner);
@@ -950,7 +950,7 @@ pub(crate) fn trait_environment_query(
950 // inside consts or type aliases) 950 // inside consts or type aliases)
951 cov_mark::hit!(trait_self_implements_self); 951 cov_mark::hit!(trait_self_implements_self);
952 let substs = Substitution::type_params(db, trait_id); 952 let substs = Substitution::type_params(db, trait_id);
953 let trait_ref = TraitRef { trait_: trait_id, substs }; 953 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs };
954 let pred = GenericPredicate::Implemented(trait_ref); 954 let pred = GenericPredicate::Implemented(trait_ref);
955 let program_clause: chalk_ir::ProgramClause<Interner> = 955 let program_clause: chalk_ir::ProgramClause<Interner> =
956 pred.clone().to_chalk(db).cast(&Interner); 956 pred.clone().to_chalk(db).cast(&Interner);
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 943d3339b..01b78fb44 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -19,6 +19,7 @@ use crate::{
19 db::HirDatabase, 19 db::HirDatabase,
20 from_foreign_def_id, 20 from_foreign_def_id,
21 primitive::{self, FloatTy, IntTy, UintTy}, 21 primitive::{self, FloatTy, IntTy, UintTy},
22 to_chalk_trait_id,
22 utils::all_super_traits, 23 utils::all_super_traits,
23 AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, ForeignDefId, InEnvironment, Interner, 24 AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, ForeignDefId, InEnvironment, Interner,
24 Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, 25 Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
@@ -101,7 +102,7 @@ impl TraitImpls {
101 for (_module_id, module_data) in crate_def_map.modules() { 102 for (_module_id, module_data) in crate_def_map.modules() {
102 for impl_id in module_data.scope.impls() { 103 for impl_id in module_data.scope.impls() {
103 let target_trait = match db.impl_trait(impl_id) { 104 let target_trait = match db.impl_trait(impl_id) {
104 Some(tr) => tr.value.trait_, 105 Some(tr) => tr.value.hir_trait_id(),
105 None => continue, 106 None => continue,
106 }; 107 };
107 let self_ty = db.impl_self_ty(impl_id); 108 let self_ty = db.impl_self_ty(impl_id);
@@ -773,7 +774,7 @@ fn generic_implements_goal(
773 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) 774 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
774 .build(); 775 .build();
775 kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1)); 776 kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1));
776 let trait_ref = TraitRef { trait_, substs }; 777 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs };
777 let obligation = super::Obligation::Trait(trait_ref); 778 let obligation = super::Obligation::Trait(trait_ref);
778 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } 779 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
779} 780}
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index 40eb1034e..a7287dea1 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -137,7 +137,7 @@ pub(crate) fn trait_solve_query(
137 goal: Canonical<InEnvironment<Obligation>>, 137 goal: Canonical<InEnvironment<Obligation>>,
138) -> Option<Solution> { 138) -> Option<Solution> {
139 let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { 139 let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value {
140 Obligation::Trait(it) => db.trait_data(it.trait_).name.to_string(), 140 Obligation::Trait(it) => db.trait_data(it.hir_trait_id()).name.to_string(),
141 Obligation::Projection(_) => "projection".to_string(), 141 Obligation::Projection(_) => "projection".to_string(),
142 }); 142 });
143 log::info!("trait_solve_query({})", goal.value.value.display(db)); 143 log::info!("trait_solve_query({})", goal.value.value.display(db));
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index bef6e7e9c..bac70f5aa 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -19,7 +19,7 @@ use crate::{
19 display::HirDisplay, 19 display::HirDisplay,
20 from_assoc_type_id, 20 from_assoc_type_id,
21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, 21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
22 to_assoc_type_id, 22 to_assoc_type_id, to_chalk_trait_id,
23 utils::generics, 23 utils::generics,
24 BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, GenericPredicate, 24 BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, GenericPredicate,
25 ProjectionPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind, 25 ProjectionPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind,
@@ -219,9 +219,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
219 // for<T> <Self> [Future<Self>, Future::Output<Self> = T] 219 // for<T> <Self> [Future<Self>, Future::Output<Self> = T]
220 // ^1 ^0 ^0 ^0 ^1 220 // ^1 ^0 ^0 ^0 ^1
221 let impl_bound = GenericPredicate::Implemented(TraitRef { 221 let impl_bound = GenericPredicate::Implemented(TraitRef {
222 trait_: future_trait, 222 trait_id: to_chalk_trait_id(future_trait),
223 // Self type as the first parameter. 223 // Self type as the first parameter.
224 substs: Substitution::single( 224 substitution: Substitution::single(
225 TyKind::BoundVar(BoundVar { 225 TyKind::BoundVar(BoundVar {
226 debruijn: DebruijnIndex::INNERMOST, 226 debruijn: DebruijnIndex::INNERMOST,
227 index: 0, 227 index: 0,
@@ -546,7 +546,7 @@ fn impl_def_datum(
546 546
547 let generic_params = generics(db.upcast(), impl_id.into()); 547 let generic_params = generics(db.upcast(), impl_id.into());
548 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 548 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
549 let trait_ = trait_ref.trait_; 549 let trait_ = trait_ref.hir_trait_id();
550 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { 550 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate {
551 rust_ir::ImplType::Local 551 rust_ir::ImplType::Local
552 } else { 552 } else {
@@ -614,7 +614,7 @@ fn type_alias_associated_ty_value(
614 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved 614 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved
615 615
616 let assoc_ty = db 616 let assoc_ty = db
617 .trait_data(trait_ref.trait_) 617 .trait_data(trait_ref.hir_trait_id())
618 .associated_type_by_name(&type_alias_data.name) 618 .associated_type_by_name(&type_alias_data.name)
619 .expect("assoc ty value should not exist"); // validated when building the impl data as well 619 .expect("assoc ty value should not exist"); // validated when building the impl data as well
620 let ty = db.ty(type_alias.into()); 620 let ty = db.ty(type_alias.into());
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index d969527dc..0086ce1e9 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -239,15 +239,15 @@ impl ToChalk for TraitRef {
239 type Chalk = chalk_ir::TraitRef<Interner>; 239 type Chalk = chalk_ir::TraitRef<Interner>;
240 240
241 fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> { 241 fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> {
242 let trait_id = self.trait_.to_chalk(db); 242 let trait_id = self.trait_id;
243 let substitution = self.substs.to_chalk(db); 243 let substitution = self.substitution.to_chalk(db);
244 chalk_ir::TraitRef { trait_id, substitution } 244 chalk_ir::TraitRef { trait_id, substitution }
245 } 245 }
246 246
247 fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self { 247 fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self {
248 let trait_ = from_chalk(db, trait_ref.trait_id); 248 let trait_id = trait_ref.trait_id;
249 let substs = from_chalk(db, trait_ref.substitution); 249 let substs = from_chalk(db, trait_ref.substitution);
250 TraitRef { trait_, substs } 250 TraitRef { trait_id, substitution: substs }
251 } 251 }
252} 252}
253 253
@@ -515,17 +515,16 @@ pub(super) fn generic_predicate_to_inline_bound(
515 // We don't have a special type for this, but Chalk does. 515 // We don't have a special type for this, but Chalk does.
516 match pred { 516 match pred {
517 GenericPredicate::Implemented(trait_ref) => { 517 GenericPredicate::Implemented(trait_ref) => {
518 if &trait_ref.substs[0] != self_ty { 518 if &trait_ref.substitution[0] != self_ty {
519 // we can only convert predicates back to type bounds if they 519 // we can only convert predicates back to type bounds if they
520 // have the expected self type 520 // have the expected self type
521 return None; 521 return None;
522 } 522 }
523 let args_no_self = trait_ref.substs[1..] 523 let args_no_self = trait_ref.substitution[1..]
524 .iter() 524 .iter()
525 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 525 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
526 .collect(); 526 .collect();
527 let trait_bound = 527 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
528 rust_ir::TraitBound { trait_id: trait_ref.trait_.to_chalk(db), args_no_self };
529 Some(rust_ir::InlineBound::TraitBound(trait_bound)) 528 Some(rust_ir::InlineBound::TraitBound(trait_bound))
530 } 529 }
531 GenericPredicate::Projection(proj) => { 530 GenericPredicate::Projection(proj) => {
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index 7351e4e54..b66243d48 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -55,9 +55,9 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
55 // lifetime problems, but since there usually shouldn't be more than a 55 // lifetime problems, but since there usually shouldn't be more than a
56 // few direct traits this should be fine (we could even use some kind of 56 // few direct traits this should be fine (we could even use some kind of
57 // SmallVec if performance is a concern) 57 // SmallVec if performance is a concern)
58 let generic_params = db.generic_params(trait_ref.trait_.into()); 58 let generic_params = db.generic_params(trait_ref.hir_trait_id().into());
59 let trait_self = match generic_params.find_trait_self_param() { 59 let trait_self = match generic_params.find_trait_self_param() {
60 Some(p) => TypeParamId { parent: trait_ref.trait_.into(), local_id: p }, 60 Some(p) => TypeParamId { parent: trait_ref.hir_trait_id().into(), local_id: p },
61 None => return Vec::new(), 61 None => return Vec::new(),
62 }; 62 };
63 db.generic_predicates_for_param(trait_self) 63 db.generic_predicates_for_param(trait_self)
@@ -68,7 +68,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
68 _ => None, 68 _ => None,
69 }) 69 })
70 }) 70 })
71 .map(|pred| pred.subst(&trait_ref.substs)) 71 .map(|pred| pred.subst(&trait_ref.substitution))
72 .collect() 72 .collect()
73} 73}
74 74
@@ -108,7 +108,7 @@ pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) ->
108 // yeah this is quadratic, but trait hierarchies should be flat 108 // yeah this is quadratic, but trait hierarchies should be flat
109 // enough that this doesn't matter 109 // enough that this doesn't matter
110 for tt in direct_super_trait_refs(db, t) { 110 for tt in direct_super_trait_refs(db, t) {
111 if !result.iter().any(|tr| tr.trait_ == tt.trait_) { 111 if !result.iter().any(|tr| tr.trait_id == tt.trait_id) {
112 result.push(tt); 112 result.push(tt);
113 } 113 }
114 } 114 }
@@ -123,7 +123,7 @@ pub(super) fn associated_type_by_name_including_super_traits(
123 name: &Name, 123 name: &Name,
124) -> Option<(TraitRef, TypeAliasId)> { 124) -> Option<(TraitRef, TypeAliasId)> {
125 all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| { 125 all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| {
126 let assoc_type = db.trait_data(t.trait_).associated_type_by_name(name)?; 126 let assoc_type = db.trait_data(t.hir_trait_id()).associated_type_by_name(name)?;
127 Some((t, assoc_type)) 127 Some((t, assoc_type))
128 }) 128 })
129} 129}
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index c086de163..364be260c 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -339,10 +339,14 @@ impl TryToNav for hir::Field {
339impl TryToNav for hir::MacroDef { 339impl TryToNav for hir::MacroDef {
340 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { 340 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
341 let src = self.source(db)?; 341 let src = self.source(db)?;
342 log::debug!("nav target {:#?}", src.value.syntax()); 342 let name_owner: &dyn ast::NameOwner = match &src.value {
343 Either::Left(it) => it,
344 Either::Right(it) => it,
345 };
346 log::debug!("nav target {:#?}", name_owner.syntax());
343 let mut res = NavigationTarget::from_named( 347 let mut res = NavigationTarget::from_named(
344 db, 348 db,
345 src.as_ref().map(|it| it as &dyn ast::NameOwner), 349 src.as_ref().with_value(name_owner),
346 SymbolKind::Macro, 350 SymbolKind::Macro,
347 ); 351 );
348 res.docs = self.docs(db); 352 res.docs = self.docs(db);
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 598b47e41..473d48c2f 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1176,4 +1176,21 @@ fn foo() { A { a$0: }; }
1176"#, 1176"#,
1177 ) 1177 )
1178 } 1178 }
1179
1180 #[test]
1181 fn goto_proc_macro() {
1182 check(
1183 r#"
1184//- /main.rs crate:main deps:mac
1185use mac::fn_macro;
1186
1187fn_macro$0!();
1188
1189//- /mac.rs crate:mac
1190#[proc_macro]
1191fn fn_macro() {}
1192 //^^^^^^^^
1193 "#,
1194 )
1195 }
1179} 1196}
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 15d309d7d..a3fb17c0a 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -331,10 +331,16 @@ fn hover_for_definition(
331) -> Option<Markup> { 331) -> Option<Markup> {
332 let mod_path = definition_mod_path(db, &def); 332 let mod_path = definition_mod_path(db, &def);
333 return match def { 333 return match def {
334 Definition::Macro(it) => { 334 Definition::Macro(it) => match &it.source(db)?.value {
335 let label = macro_label(&it.source(db)?.value); 335 Either::Left(mac) => {
336 from_def_source_labeled(db, it, Some(label), mod_path) 336 let label = macro_label(&mac);
337 } 337 from_def_source_labeled(db, it, Some(label), mod_path)
338 }
339 Either::Right(_) => {
340 // FIXME
341 None
342 }
343 },
338 Definition::Field(def) => from_hir_fmt(db, def, mod_path), 344 Definition::Field(def) => from_hir_fmt(db, def, mod_path),
339 Definition::ModuleDef(it) => match it { 345 Definition::ModuleDef(it) => match it {
340 ModuleDef::Module(it) => from_hir_fmt(db, it, mod_path), 346 ModuleDef::Module(it) => from_hir_fmt(db, it, mod_path),
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index ba3447b3a..e25b698e0 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -12,7 +12,7 @@ mod html;
12#[cfg(test)] 12#[cfg(test)]
13mod tests; 13mod tests;
14 14
15use hir::{Name, Semantics}; 15use hir::{InFile, Name, Semantics};
16use ide_db::{RootDatabase, SymbolKind}; 16use ide_db::{RootDatabase, SymbolKind};
17use rustc_hash::FxHashMap; 17use rustc_hash::FxHashMap;
18use syntax::{ 18use syntax::{
@@ -73,14 +73,20 @@ pub(crate) fn highlight(
73 }; 73 };
74 74
75 let mut hl = highlights::Highlights::new(root.text_range()); 75 let mut hl = highlights::Highlights::new(root.text_range());
76 traverse(&mut hl, &sema, &root, range_to_highlight, syntactic_name_ref_highlighting); 76 traverse(
77 &mut hl,
78 &sema,
79 InFile::new(file_id.into(), &root),
80 range_to_highlight,
81 syntactic_name_ref_highlighting,
82 );
77 hl.to_vec() 83 hl.to_vec()
78} 84}
79 85
80fn traverse( 86fn traverse(
81 hl: &mut Highlights, 87 hl: &mut Highlights,
82 sema: &Semantics<RootDatabase>, 88 sema: &Semantics<RootDatabase>,
83 root: &SyntaxNode, 89 root: InFile<&SyntaxNode>,
84 range_to_highlight: TextRange, 90 range_to_highlight: TextRange,
85 syntactic_name_ref_highlighting: bool, 91 syntactic_name_ref_highlighting: bool,
86) { 92) {
@@ -93,7 +99,7 @@ fn traverse(
93 99
94 // Walk all nodes, keeping track of whether we are inside a macro or not. 100 // Walk all nodes, keeping track of whether we are inside a macro or not.
95 // If in macro, expand it first and highlight the expanded code. 101 // If in macro, expand it first and highlight the expanded code.
96 for event in root.preorder_with_tokens() { 102 for event in root.value.preorder_with_tokens() {
97 let event_range = match &event { 103 let event_range = match &event {
98 WalkEvent::Enter(it) | WalkEvent::Leave(it) => it.text_range(), 104 WalkEvent::Enter(it) | WalkEvent::Leave(it) => it.text_range(),
99 }; 105 };
@@ -150,7 +156,7 @@ fn traverse(
150 WalkEvent::Enter(it) => it, 156 WalkEvent::Enter(it) => it,
151 WalkEvent::Leave(it) => { 157 WalkEvent::Leave(it) => {
152 if let Some(node) = it.as_node() { 158 if let Some(node) = it.as_node() {
153 inject::doc_comment(hl, sema, node); 159 inject::doc_comment(hl, sema, root.with_value(node));
154 } 160 }
155 continue; 161 continue;
156 } 162 }
diff --git a/crates/ide/src/syntax_highlighting/html.rs b/crates/ide/src/syntax_highlighting/html.rs
index 1d34731ab..5327af845 100644
--- a/crates/ide/src/syntax_highlighting/html.rs
+++ b/crates/ide/src/syntax_highlighting/html.rs
@@ -59,7 +59,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
59.label { color: #DFAF8F; font-style: italic; } 59.label { color: #DFAF8F; font-style: italic; }
60.comment { color: #7F9F7F; } 60.comment { color: #7F9F7F; }
61.documentation { color: #629755; } 61.documentation { color: #629755; }
62.intra_doc_link { color: #A9C577; } 62.intra_doc_link { font-style: italic; }
63.injected { opacity: 0.65 ; } 63.injected { opacity: 0.65 ; }
64.struct, .enum { color: #7CB8BB; } 64.struct, .enum { color: #7CB8BB; }
65.enum_variant { color: #BDE0F3; } 65.enum_variant { color: #BDE0F3; }
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs
index 947cc974c..f359eacf2 100644
--- a/crates/ide/src/syntax_highlighting/inject.rs
+++ b/crates/ide/src/syntax_highlighting/inject.rs
@@ -3,8 +3,8 @@
3use std::{mem, ops::Range}; 3use std::{mem, ops::Range};
4 4
5use either::Either; 5use either::Either;
6use hir::{HasAttrs, Semantics}; 6use hir::{HasAttrs, InFile, Semantics};
7use ide_db::{call_info::ActiveParameter, defs::Definition}; 7use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind};
8use syntax::{ 8use syntax::{
9 ast::{self, AstNode, AttrsOwner, DocCommentsOwner}, 9 ast::{self, AstNode, AttrsOwner, DocCommentsOwner},
10 match_ast, AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, 10 match_ast, AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize,
@@ -148,8 +148,12 @@ fn doc_attributes<'node>(
148} 148}
149 149
150/// Injection of syntax highlighting of doctests. 150/// Injection of syntax highlighting of doctests.
151pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, node: &SyntaxNode) { 151pub(super) fn doc_comment(
152 let (owner, attributes, def) = match doc_attributes(sema, node) { 152 hl: &mut Highlights,
153 sema: &Semantics<RootDatabase>,
154 node: InFile<&SyntaxNode>,
155) {
156 let (owner, attributes, def) = match doc_attributes(sema, node.value) {
153 Some(it) => it, 157 Some(it) => it,
154 None => return, 158 None => return,
155 }; 159 };
@@ -157,7 +161,12 @@ pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, n
157 let mut inj = Injector::default(); 161 let mut inj = Injector::default();
158 inj.add_unmapped("fn doctest() {\n"); 162 inj.add_unmapped("fn doctest() {\n");
159 163
160 let attrs_source_map = attributes.source_map(&owner); 164 let attrs_source_map = match def {
165 Definition::ModuleDef(hir::ModuleDef::Module(module)) => {
166 attributes.source_map_for_module(sema.db, module.into())
167 }
168 _ => attributes.source_map(node.with_value(&owner)),
169 };
161 170
162 let mut is_codeblock = false; 171 let mut is_codeblock = false;
163 let mut is_doctest = false; 172 let mut is_doctest = false;
@@ -168,7 +177,10 @@ pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, n
168 let mut intra_doc_links = Vec::new(); 177 let mut intra_doc_links = Vec::new();
169 let mut string; 178 let mut string;
170 for attr in attributes.by_key("doc").attrs() { 179 for attr in attributes.by_key("doc").attrs() {
171 let src = attrs_source_map.source_of(&attr); 180 let InFile { file_id, value: src } = attrs_source_map.source_of(&attr);
181 if file_id != node.file_id {
182 continue;
183 }
172 let (line, range, prefix) = match &src { 184 let (line, range, prefix) = match &src {
173 Either::Left(it) => { 185 Either::Left(it) => {
174 string = match find_doc_string_in_attr(attr, it) { 186 string = match find_doc_string_in_attr(attr, it) {
@@ -213,13 +225,16 @@ pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, n
213 intra_doc_links.extend( 225 intra_doc_links.extend(
214 extract_definitions_from_markdown(line) 226 extract_definitions_from_markdown(line)
215 .into_iter() 227 .into_iter()
216 .filter(|(link, ns, _)| { 228 .filter_map(|(link, ns, range)| {
217 validate_intra_doc_link(sema.db, &def, link, *ns) 229 validate_intra_doc_link(sema.db, &def, &link, ns).zip(Some(range))
218 }) 230 })
219 .map(|(.., Range { start, end })| { 231 .map(|(def, Range { start, end })| {
220 TextRange::at( 232 (
221 prev_range_start + TextSize::from(start as u32), 233 def,
222 TextSize::from((end - start) as u32), 234 TextRange::at(
235 prev_range_start + TextSize::from(start as u32),
236 TextSize::from((end - start) as u32),
237 ),
223 ) 238 )
224 }), 239 }),
225 ); 240 );
@@ -243,10 +258,13 @@ pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, n
243 } 258 }
244 } 259 }
245 260
246 for range in intra_doc_links { 261 for (def, range) in intra_doc_links {
247 hl.add(HlRange { 262 hl.add(HlRange {
248 range, 263 range,
249 highlight: HlTag::IntraDocLink | HlMod::Documentation, 264 highlight: module_def_to_hl_tag(def)
265 | HlMod::Documentation
266 | HlMod::Injected
267 | HlMod::IntraDocLink,
250 binding_hash: None, 268 binding_hash: None,
251 }); 269 });
252 } 270 }
@@ -305,7 +323,7 @@ fn validate_intra_doc_link(
305 def: &Definition, 323 def: &Definition,
306 link: &str, 324 link: &str,
307 ns: Option<hir::Namespace>, 325 ns: Option<hir::Namespace>,
308) -> bool { 326) -> Option<hir::ModuleDef> {
309 match def { 327 match def {
310 Definition::ModuleDef(def) => match def { 328 Definition::ModuleDef(def) => match def {
311 hir::ModuleDef::Module(it) => it.resolve_doc_path(db, &link, ns), 329 hir::ModuleDef::Module(it) => it.resolve_doc_path(db, &link, ns),
@@ -325,5 +343,21 @@ fn validate_intra_doc_link(
325 | Definition::GenericParam(_) 343 | Definition::GenericParam(_)
326 | Definition::Label(_) => None, 344 | Definition::Label(_) => None,
327 } 345 }
328 .is_some() 346}
347
348fn module_def_to_hl_tag(def: hir::ModuleDef) -> HlTag {
349 let symbol = match def {
350 hir::ModuleDef::Module(_) => SymbolKind::Module,
351 hir::ModuleDef::Function(_) => SymbolKind::Function,
352 hir::ModuleDef::Adt(hir::Adt::Struct(_)) => SymbolKind::Struct,
353 hir::ModuleDef::Adt(hir::Adt::Enum(_)) => SymbolKind::Enum,
354 hir::ModuleDef::Adt(hir::Adt::Union(_)) => SymbolKind::Union,
355 hir::ModuleDef::Variant(_) => SymbolKind::Variant,
356 hir::ModuleDef::Const(_) => SymbolKind::Const,
357 hir::ModuleDef::Static(_) => SymbolKind::Static,
358 hir::ModuleDef::Trait(_) => SymbolKind::Trait,
359 hir::ModuleDef::TypeAlias(_) => SymbolKind::TypeAlias,
360 hir::ModuleDef::BuiltinType(_) => return HlTag::BuiltinType,
361 };
362 HlTag::Symbol(symbol)
329} 363}
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index ce46e5127..93db79b89 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -26,7 +26,6 @@ pub enum HlTag {
26 Comment, 26 Comment,
27 EscapeSequence, 27 EscapeSequence,
28 FormatSpecifier, 28 FormatSpecifier,
29 IntraDocLink,
30 Keyword, 29 Keyword,
31 NumericLiteral, 30 NumericLiteral,
32 Operator, 31 Operator,
@@ -57,6 +56,8 @@ pub enum HlMod {
57 Static, 56 Static,
58 /// Used for items in impls&traits. 57 /// Used for items in impls&traits.
59 Associated, 58 Associated,
59 /// Used for intra doc links in doc injection.
60 IntraDocLink,
60 61
61 /// Keep this last! 62 /// Keep this last!
62 Unsafe, 63 Unsafe,
@@ -117,7 +118,6 @@ impl HlTag {
117 HlTag::Comment => "comment", 118 HlTag::Comment => "comment",
118 HlTag::EscapeSequence => "escape_sequence", 119 HlTag::EscapeSequence => "escape_sequence",
119 HlTag::FormatSpecifier => "format_specifier", 120 HlTag::FormatSpecifier => "format_specifier",
120 HlTag::IntraDocLink => "intra_doc_link",
121 HlTag::Keyword => "keyword", 121 HlTag::Keyword => "keyword",
122 HlTag::Punctuation(punct) => match punct { 122 HlTag::Punctuation(punct) => match punct {
123 HlPunct::Bracket => "bracket", 123 HlPunct::Bracket => "bracket",
@@ -151,6 +151,7 @@ impl HlMod {
151 HlMod::ControlFlow, 151 HlMod::ControlFlow,
152 HlMod::Definition, 152 HlMod::Definition,
153 HlMod::Documentation, 153 HlMod::Documentation,
154 HlMod::IntraDocLink,
154 HlMod::Injected, 155 HlMod::Injected,
155 HlMod::Mutable, 156 HlMod::Mutable,
156 HlMod::Consuming, 157 HlMod::Consuming,
@@ -162,17 +163,18 @@ impl HlMod {
162 163
163 fn as_str(self) -> &'static str { 164 fn as_str(self) -> &'static str {
164 match self { 165 match self {
166 HlMod::Associated => "associated",
165 HlMod::Attribute => "attribute", 167 HlMod::Attribute => "attribute",
168 HlMod::Callable => "callable",
169 HlMod::Consuming => "consuming",
166 HlMod::ControlFlow => "control", 170 HlMod::ControlFlow => "control",
167 HlMod::Definition => "declaration", 171 HlMod::Definition => "declaration",
168 HlMod::Documentation => "documentation", 172 HlMod::Documentation => "documentation",
169 HlMod::Injected => "injected", 173 HlMod::Injected => "injected",
174 HlMod::IntraDocLink => "intra_doc_link",
170 HlMod::Mutable => "mutable", 175 HlMod::Mutable => "mutable",
171 HlMod::Consuming => "consuming",
172 HlMod::Unsafe => "unsafe",
173 HlMod::Callable => "callable",
174 HlMod::Static => "static", 176 HlMod::Static => "static",
175 HlMod::Associated => "associated", 177 HlMod::Unsafe => "unsafe",
176 } 178 }
177 } 179 }
178 180
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
index 60c7518af..4635ea927 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
7.label { color: #DFAF8F; font-style: italic; } 7.label { color: #DFAF8F; font-style: italic; }
8.comment { color: #7F9F7F; } 8.comment { color: #7F9F7F; }
9.documentation { color: #629755; } 9.documentation { color: #629755; }
10.intra_doc_link { color: #A9C577; } 10.intra_doc_link { font-style: italic; }
11.injected { opacity: 0.65 ; } 11.injected { opacity: 0.65 ; }
12.struct, .enum { color: #7CB8BB; } 12.struct, .enum { color: #7CB8BB; }
13.enum_variant { color: #BDE0F3; } 13.enum_variant { color: #BDE0F3; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 5d802a647..045162eb8 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
7.label { color: #DFAF8F; font-style: italic; } 7.label { color: #DFAF8F; font-style: italic; }
8.comment { color: #7F9F7F; } 8.comment { color: #7F9F7F; }
9.documentation { color: #629755; } 9.documentation { color: #629755; }
10.intra_doc_link { color: #A9C577; } 10.intra_doc_link { font-style: italic; }
11.injected { opacity: 0.65 ; } 11.injected { opacity: 0.65 ; }
12.struct, .enum { color: #7CB8BB; } 12.struct, .enum { color: #7CB8BB; }
13.enum_variant { color: #BDE0F3; } 13.enum_variant { color: #BDE0F3; }
@@ -99,8 +99,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
99 <span class="brace">}</span> 99 <span class="brace">}</span>
100<span class="brace">}</span> 100<span class="brace">}</span>
101 101
102<span class="comment documentation">/// </span><span class="intra_doc_link documentation">[`Foo`](Foo)</span><span class="comment documentation"> is a struct</span> 102<span class="comment documentation">/// </span><span class="struct documentation intra_doc_link injected">[`Foo`](Foo)</span><span class="comment documentation"> is a struct</span>
103<span class="comment documentation">/// </span><span class="intra_doc_link documentation">[`all_the_links`](all_the_links)</span><span class="comment documentation"> is this function</span> 103<span class="comment documentation">/// </span><span class="function documentation intra_doc_link injected">[`all_the_links`](all_the_links)</span><span class="comment documentation"> is this function</span>
104<span class="comment documentation">/// [`noop`](noop) is a macro below</span> 104<span class="comment documentation">/// [`noop`](noop) is a macro below</span>
105<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">all_the_links</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 105<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">all_the_links</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
106 106
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
index 4e312765c..ca9bb1e7d 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
7.label { color: #DFAF8F; font-style: italic; } 7.label { color: #DFAF8F; font-style: italic; }
8.comment { color: #7F9F7F; } 8.comment { color: #7F9F7F; }
9.documentation { color: #629755; } 9.documentation { color: #629755; }
10.intra_doc_link { color: #A9C577; } 10.intra_doc_link { font-style: italic; }
11.injected { opacity: 0.65 ; } 11.injected { opacity: 0.65 ; }
12.struct, .enum { color: #7CB8BB; } 12.struct, .enum { color: #7CB8BB; }
13.enum_variant { color: #BDE0F3; } 13.enum_variant { color: #BDE0F3; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
index 57dfe7509..9215ddd9e 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
7.label { color: #DFAF8F; font-style: italic; } 7.label { color: #DFAF8F; font-style: italic; }
8.comment { color: #7F9F7F; } 8.comment { color: #7F9F7F; }
9.documentation { color: #629755; } 9.documentation { color: #629755; }
10.intra_doc_link { color: #A9C577; } 10.intra_doc_link { font-style: italic; }
11.injected { opacity: 0.65 ; } 11.injected { opacity: 0.65 ; }
12.struct, .enum { color: #7CB8BB; } 12.struct, .enum { color: #7CB8BB; }
13.enum_variant { color: #BDE0F3; } 13.enum_variant { color: #BDE0F3; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index 75dbd0f14..e860d713e 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
7.label { color: #DFAF8F; font-style: italic; } 7.label { color: #DFAF8F; font-style: italic; }
8.comment { color: #7F9F7F; } 8.comment { color: #7F9F7F; }
9.documentation { color: #629755; } 9.documentation { color: #629755; }
10.intra_doc_link { color: #A9C577; } 10.intra_doc_link { font-style: italic; }
11.injected { opacity: 0.65 ; } 11.injected { opacity: 0.65 ; }
12.struct, .enum { color: #7CB8BB; } 12.struct, .enum { color: #7CB8BB; }
13.enum_variant { color: #BDE0F3; } 13.enum_variant { color: #BDE0F3; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 423256a20..6a6555208 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
7.label { color: #DFAF8F; font-style: italic; } 7.label { color: #DFAF8F; font-style: italic; }
8.comment { color: #7F9F7F; } 8.comment { color: #7F9F7F; }
9.documentation { color: #629755; } 9.documentation { color: #629755; }
10.intra_doc_link { color: #A9C577; } 10.intra_doc_link { font-style: italic; }
11.injected { opacity: 0.65 ; } 11.injected { opacity: 0.65 ; }
12.struct, .enum { color: #7CB8BB; } 12.struct, .enum { color: #7CB8BB; }
13.enum_variant { color: #BDE0F3; } 13.enum_variant { color: #BDE0F3; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index fffe8c0f5..8b2dd3b70 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
7.label { color: #DFAF8F; font-style: italic; } 7.label { color: #DFAF8F; font-style: italic; }
8.comment { color: #7F9F7F; } 8.comment { color: #7F9F7F; }
9.documentation { color: #629755; } 9.documentation { color: #629755; }
10.intra_doc_link { color: #A9C577; } 10.intra_doc_link { font-style: italic; }
11.injected { opacity: 0.65 ; } 11.injected { opacity: 0.65 ; }
12.struct, .enum { color: #7CB8BB; } 12.struct, .enum { color: #7CB8BB; }
13.enum_variant { color: #BDE0F3; } 13.enum_variant { color: #BDE0F3; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/injection.html b/crates/ide/src/syntax_highlighting/test_data/injection.html
index 34d8deb68..9ab46d05c 100644
--- a/crates/ide/src/syntax_highlighting/test_data/injection.html
+++ b/crates/ide/src/syntax_highlighting/test_data/injection.html
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
7.label { color: #DFAF8F; font-style: italic; } 7.label { color: #DFAF8F; font-style: italic; }
8.comment { color: #7F9F7F; } 8.comment { color: #7F9F7F; }
9.documentation { color: #629755; } 9.documentation { color: #629755; }
10.intra_doc_link { color: #A9C577; } 10.intra_doc_link { font-style: italic; }
11.injected { opacity: 0.65 ; } 11.injected { opacity: 0.65 ; }
12.struct, .enum { color: #7CB8BB; } 12.struct, .enum { color: #7CB8BB; }
13.enum_variant { color: #BDE0F3; } 13.enum_variant { color: #BDE0F3; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html b/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html
index d9ca3a4c4..666b0b228 100644
--- a/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
7.label { color: #DFAF8F; font-style: italic; } 7.label { color: #DFAF8F; font-style: italic; }
8.comment { color: #7F9F7F; } 8.comment { color: #7F9F7F; }
9.documentation { color: #629755; } 9.documentation { color: #629755; }
10.intra_doc_link { color: #A9C577; } 10.intra_doc_link { font-style: italic; }
11.injected { opacity: 0.65 ; } 11.injected { opacity: 0.65 ; }
12.struct, .enum { color: #7CB8BB; } 12.struct, .enum { color: #7CB8BB; }
13.enum_variant { color: #BDE0F3; } 13.enum_variant { color: #BDE0F3; }
diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs
index 3fa21ba7c..7578ad50b 100644
--- a/crates/ide_completion/src/render/macro_.rs
+++ b/crates/ide_completion/src/render/macro_.rs
@@ -91,7 +91,7 @@ impl<'a> MacroRender<'a> {
91 } 91 }
92 92
93 fn detail(&self) -> Option<String> { 93 fn detail(&self) -> Option<String> {
94 let ast_node = self.macro_.source(self.ctx.db())?.value; 94 let ast_node = self.macro_.source(self.ctx.db())?.value.left()?;
95 Some(macro_label(&ast_node)) 95 Some(macro_label(&ast_node))
96 } 96 }
97} 97}
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index 0cb7d12a7..a3c5e9ccf 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -52,7 +52,6 @@ define_semantic_token_types![
52 (ESCAPE_SEQUENCE, "escapeSequence"), 52 (ESCAPE_SEQUENCE, "escapeSequence"),
53 (FORMAT_SPECIFIER, "formatSpecifier"), 53 (FORMAT_SPECIFIER, "formatSpecifier"),
54 (GENERIC, "generic"), 54 (GENERIC, "generic"),
55 (INTRA_DOC_LINK, "intraDocLink"),
56 (LABEL, "label"), 55 (LABEL, "label"),
57 (LIFETIME, "lifetime"), 56 (LIFETIME, "lifetime"),
58 (PARENTHESIS, "parenthesis"), 57 (PARENTHESIS, "parenthesis"),
@@ -90,6 +89,7 @@ define_semantic_token_modifiers![
90 (UNSAFE, "unsafe"), 89 (UNSAFE, "unsafe"),
91 (ATTRIBUTE_MODIFIER, "attribute"), 90 (ATTRIBUTE_MODIFIER, "attribute"),
92 (CALLABLE, "callable"), 91 (CALLABLE, "callable"),
92 (INTRA_DOC_LINK, "intraDocLink"),
93]; 93];
94 94
95#[derive(Default)] 95#[derive(Default)]
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 70501618e..1ddea9278 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -443,7 +443,6 @@ fn semantic_token_type_and_modifiers(
443 HlTag::Comment => lsp_types::SemanticTokenType::COMMENT, 443 HlTag::Comment => lsp_types::SemanticTokenType::COMMENT,
444 HlTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE, 444 HlTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE,
445 HlTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER, 445 HlTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER,
446 HlTag::IntraDocLink => semantic_tokens::INTRA_DOC_LINK,
447 HlTag::Keyword => lsp_types::SemanticTokenType::KEYWORD, 446 HlTag::Keyword => lsp_types::SemanticTokenType::KEYWORD,
448 HlTag::None => semantic_tokens::GENERIC, 447 HlTag::None => semantic_tokens::GENERIC,
449 HlTag::Operator => lsp_types::SemanticTokenType::OPERATOR, 448 HlTag::Operator => lsp_types::SemanticTokenType::OPERATOR,
@@ -474,6 +473,7 @@ fn semantic_token_type_and_modifiers(
474 HlMod::Unsafe => semantic_tokens::UNSAFE, 473 HlMod::Unsafe => semantic_tokens::UNSAFE,
475 HlMod::Callable => semantic_tokens::CALLABLE, 474 HlMod::Callable => semantic_tokens::CALLABLE,
476 HlMod::Static => lsp_types::SemanticTokenModifier::STATIC, 475 HlMod::Static => lsp_types::SemanticTokenModifier::STATIC,
476 HlMod::IntraDocLink => semantic_tokens::INTRA_DOC_LINK,
477 HlMod::Associated => continue, 477 HlMod::Associated => continue,
478 }; 478 };
479 mods |= modifier; 479 mods |= modifier;
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index f4c37353c..dba2197de 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -384,11 +384,9 @@ If the LSP binary is not available, GNOME Builder can install it when opening a
384 384
385=== Eclipse IDE 385=== Eclipse IDE
386 386
387Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
388
389Support for Rust development in the Eclipse IDE is provided by link:https://github.com/eclipse/corrosion[Eclipse Corrosion]. 387Support for Rust development in the Eclipse IDE is provided by link:https://github.com/eclipse/corrosion[Eclipse Corrosion].
390While it currently uses RLS as default, you can successfully configure it so the IDE will use `rust-analyzer` instead. 388If available in PATH or in some standard location, `rust-analyzer` is detected and powers editing of Rust files without further configuration.
391To do so, with an Eclipse IDE where Corrosion is installed, just go to __Window > Preferences > Rust__ and edit the __Path to Rust Language Server__ entry to reference the path to `rust-analyzer`. 389If `rust-analyzer` is not detected, Corrosion will prompt you for configuration of your Rust toolchain and language server with a link to the __Window > Preferences > Rust__ preference page; from here a button allows to download and configure `rust-analyzer`, but you can also reference another installation.
392You'll need to close and reopen all .rs and Cargo files, or to restart the IDE, for this change to take effect. 390You'll need to close and reopen all .rs and Cargo files, or to restart the IDE, for this change to take effect.
393 391
394== Configuration 392== Configuration