aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-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
51 files changed, 479 insertions, 233 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;