diff options
52 files changed, 481 insertions, 237 deletions
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index 262002671..d57fad9ed 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs | |||
@@ -6,7 +6,7 @@ use hir_def::{ | |||
6 | src::{HasChildSource, HasSource as _}, | 6 | src::{HasChildSource, HasSource as _}, |
7 | Lookup, VariantId, | 7 | Lookup, VariantId, |
8 | }; | 8 | }; |
9 | use hir_expand::InFile; | 9 | use hir_expand::{InFile, MacroDefKind}; |
10 | use syntax::ast; | 10 | use syntax::ast; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
@@ -111,10 +111,17 @@ impl HasSource for TypeAlias { | |||
111 | } | 111 | } |
112 | } | 112 | } |
113 | impl HasSource for MacroDef { | 113 | impl 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 | } |
120 | impl HasSource for Impl { | 127 | impl 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 | ||
381 | pub struct AttrSourceMap { | 424 | pub struct AttrSourceMap { |
382 | attrs: Vec<Either<ast::Attr, ast::Comment>>, | 425 | attrs: Vec<InFile<Either<ast::Attr, ast::Comment>>>, |
383 | } | 426 | } |
384 | 427 | ||
385 | impl AttrSourceMap { | 428 | impl 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)] |
55 | mod tests; | 55 | mod tests; |
56 | mod proc_macro; | ||
56 | 57 | ||
57 | use std::sync::Arc; | 58 | use std::sync::Arc; |
58 | 59 | ||
59 | use base_db::{CrateId, Edition, FileId}; | 60 | use base_db::{CrateId, Edition, FileId}; |
60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; | 61 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId}; |
61 | use la_arena::Arena; | 62 | use la_arena::Arena; |
62 | use profile::Count; | 63 | use profile::Count; |
63 | use rustc_hash::FxHashMap; | 64 | use 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 | ||
77 | use 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::{ | |||
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
20 | use syntax::ast; | 20 | use syntax::ast; |
21 | use tt::{Leaf, TokenTree}; | ||
22 | 21 | ||
23 | use crate::{ | 22 | use crate::{ |
24 | attr::Attrs, | 23 | attr::Attrs, |
@@ -42,6 +41,8 @@ use crate::{ | |||
42 | UnresolvedMacro, | 41 | UnresolvedMacro, |
43 | }; | 42 | }; |
44 | 43 | ||
44 | use super::proc_macro::ProcMacroDef; | ||
45 | |||
45 | const GLOB_RECURSION_LIMIT: usize = 100; | 46 | const GLOB_RECURSION_LIMIT: usize = 100; |
46 | const EXPANSION_DEPTH_LIMIT: usize = 128; | 47 | const EXPANSION_DEPTH_LIMIT: usize = 128; |
47 | const FIXED_POINT_LIMIT: usize = 8192; | 48 | const 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(¯o_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 | |||
3 | use hir_expand::name::{AsName, Name}; | ||
4 | use tt::{Leaf, TokenTree}; | ||
5 | |||
6 | use crate::attr::Attrs; | ||
7 | |||
8 | #[derive(Debug, PartialEq, Eq)] | ||
9 | pub(super) struct ProcMacroDef { | ||
10 | pub(super) name: Name, | ||
11 | pub(super) kind: ProcMacroKind, | ||
12 | } | ||
13 | |||
14 | #[derive(Debug, PartialEq, Eq)] | ||
15 | pub(super) enum ProcMacroKind { | ||
16 | CustomDerive { helpers: Box<[Name]> }, | ||
17 | FnLike, | ||
18 | Attr, | ||
19 | } | ||
20 | |||
21 | impl 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 @@ | |||
1 | use super::*; | 1 | use super::*; |
2 | use crate::nameres::proc_macro::{ProcMacroDef, ProcMacroKind}; | ||
2 | 3 | ||
3 | #[test] | 4 | #[test] |
4 | fn macro_rules_are_globally_visible() { | 5 | fn macro_rules_are_globally_visible() { |
@@ -790,3 +791,28 @@ fn proc_macro_censoring() { | |||
790 | "#]], | 791 | "#]], |
791 | ); | 792 | ); |
792 | } | 793 | } |
794 | |||
795 | #[test] | ||
796 | fn 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(¯o_rules.name().unwrap().as_name()).unwrap(); | 512 | let expander = find_by_name(¯o_rules.name().unwrap().as_name()).unwrap(); |
513 | let ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_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(¯o_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(¯o_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 | ||
131 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { | 131 | fn 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)] |
225 | pub struct MacroDefId { | 225 | pub 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)] |
245 | pub enum MacroDefKind { | 255 | pub 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 | ||
13 | use crate::{ | 13 | use 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#" | ||
910 | fn 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 | }; |
43 | use crate::{ | 43 | use 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 | ||
48 | pub(crate) use unify::unify; | 48 | pub(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}; | |||
8 | use hir_def::lang_item::LangItemTarget; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | 9 | ||
10 | use crate::{ | 10 | use 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 | ||
14 | use super::{InEnvironment, InferenceContext}; | 15 | use 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 | }; |
10 | use hir_expand::name::Name; | 10 | use hir_expand::name::Name; |
11 | 11 | ||
12 | use crate::{method_resolution, Interner, Substitution, Ty, TyKind, ValueTyDefId}; | 12 | use crate::{ |
13 | method_resolution, to_chalk_trait_id, Interner, Substitution, Ty, TyKind, ValueTyDefId, | ||
14 | }; | ||
13 | 15 | ||
14 | use super::{ExprOrPatId, InferenceContext, TraitRef}; | 16 | use 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>; | |||
58 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; | 58 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; |
59 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; | 59 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; |
60 | 60 | ||
61 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | ||
62 | |||
61 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 63 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
62 | pub enum Lifetime { | 64 | pub enum Lifetime { |
63 | Parameter(LifetimeParamId), | 65 | Parameter(LifetimeParamId), |
@@ -81,7 +83,10 @@ pub struct ProjectionTy { | |||
81 | 83 | ||
82 | impl ProjectionTy { | 84 | impl 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)] |
498 | pub struct TraitRef { | 502 | pub 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 | ||
504 | impl TraitRef { | 507 | impl 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 | ||
510 | impl TypeWalk for TraitRef { | 517 | impl 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 | |||
1169 | pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { | ||
1170 | chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) | ||
1171 | } | ||
1172 | |||
1173 | pub 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 | ||
28 | use crate::{ | 28 | use 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 { | |||
339 | impl TryToNav for hir::MacroDef { | 339 | impl 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 | ||
1185 | use mac::fn_macro; | ||
1186 | |||
1187 | fn_macro$0!(); | ||
1188 | |||
1189 | //- /mac.rs crate:mac | ||
1190 | #[proc_macro] | ||
1191 | fn 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)] |
13 | mod tests; | 13 | mod tests; |
14 | 14 | ||
15 | use hir::{Name, Semantics}; | 15 | use hir::{InFile, Name, Semantics}; |
16 | use ide_db::{RootDatabase, SymbolKind}; | 16 | use ide_db::{RootDatabase, SymbolKind}; |
17 | use rustc_hash::FxHashMap; | 17 | use rustc_hash::FxHashMap; |
18 | use syntax::{ | 18 | use 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 | ||
80 | fn traverse( | 86 | fn 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 @@ | |||
3 | use std::{mem, ops::Range}; | 3 | use std::{mem, ops::Range}; |
4 | 4 | ||
5 | use either::Either; | 5 | use either::Either; |
6 | use hir::{HasAttrs, Semantics}; | 6 | use hir::{HasAttrs, InFile, Semantics}; |
7 | use ide_db::{call_info::ActiveParameter, defs::Definition}; | 7 | use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind}; |
8 | use syntax::{ | 8 | use 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. |
151 | pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, node: &SyntaxNode) { | 151 | pub(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 | |||
348 | fn module_def_to_hl_tag(def: hir::ModuleDef) -> HlTag { | ||
349 | let symbol = match def { | ||
350 | hir::ModuleDef::Module(_) => SymbolKind::Module, | ||
351 | hir::ModuleDef::Function(_) => SymbolKind::Function, | ||
352 | hir::ModuleDef::Adt(hir::Adt::Struct(_)) => SymbolKind::Struct, | ||
353 | hir::ModuleDef::Adt(hir::Adt::Enum(_)) => SymbolKind::Enum, | ||
354 | hir::ModuleDef::Adt(hir::Adt::Union(_)) => SymbolKind::Union, | ||
355 | hir::ModuleDef::Variant(_) => SymbolKind::Variant, | ||
356 | hir::ModuleDef::Const(_) => SymbolKind::Const, | ||
357 | hir::ModuleDef::Static(_) => SymbolKind::Static, | ||
358 | hir::ModuleDef::Trait(_) => SymbolKind::Trait, | ||
359 | hir::ModuleDef::TypeAlias(_) => SymbolKind::TypeAlias, | ||
360 | hir::ModuleDef::BuiltinType(_) => return HlTag::BuiltinType, | ||
361 | }; | ||
362 | HlTag::Symbol(symbol) | ||
329 | } | 363 | } |
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index ce46e5127..93db79b89 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs | |||
@@ -26,7 +26,6 @@ pub enum HlTag { | |||
26 | Comment, | 26 | Comment, |
27 | EscapeSequence, | 27 | EscapeSequence, |
28 | FormatSpecifier, | 28 | FormatSpecifier, |
29 | IntraDocLink, | ||
30 | Keyword, | 29 | Keyword, |
31 | NumericLiteral, | 30 | NumericLiteral, |
32 | Operator, | 31 | Operator, |
@@ -57,6 +56,8 @@ pub enum HlMod { | |||
57 | Static, | 56 | Static, |
58 | /// Used for items in impls&traits. | 57 | /// Used for items in impls&traits. |
59 | Associated, | 58 | Associated, |
59 | /// Used for intra doc links in doc injection. | ||
60 | IntraDocLink, | ||
60 | 61 | ||
61 | /// Keep this last! | 62 | /// Keep this last! |
62 | Unsafe, | 63 | Unsafe, |
@@ -117,7 +118,6 @@ impl HlTag { | |||
117 | HlTag::Comment => "comment", | 118 | HlTag::Comment => "comment", |
118 | HlTag::EscapeSequence => "escape_sequence", | 119 | HlTag::EscapeSequence => "escape_sequence", |
119 | HlTag::FormatSpecifier => "format_specifier", | 120 | HlTag::FormatSpecifier => "format_specifier", |
120 | HlTag::IntraDocLink => "intra_doc_link", | ||
121 | HlTag::Keyword => "keyword", | 121 | HlTag::Keyword => "keyword", |
122 | HlTag::Punctuation(punct) => match punct { | 122 | HlTag::Punctuation(punct) => match punct { |
123 | HlPunct::Bracket => "bracket", | 123 | HlPunct::Bracket => "bracket", |
@@ -151,6 +151,7 @@ impl HlMod { | |||
151 | HlMod::ControlFlow, | 151 | HlMod::ControlFlow, |
152 | HlMod::Definition, | 152 | HlMod::Definition, |
153 | HlMod::Documentation, | 153 | HlMod::Documentation, |
154 | HlMod::IntraDocLink, | ||
154 | HlMod::Injected, | 155 | HlMod::Injected, |
155 | HlMod::Mutable, | 156 | HlMod::Mutable, |
156 | HlMod::Consuming, | 157 | HlMod::Consuming, |
@@ -162,17 +163,18 @@ impl HlMod { | |||
162 | 163 | ||
163 | fn as_str(self) -> &'static str { | 164 | fn as_str(self) -> &'static str { |
164 | match self { | 165 | match self { |
166 | HlMod::Associated => "associated", | ||
165 | HlMod::Attribute => "attribute", | 167 | HlMod::Attribute => "attribute", |
168 | HlMod::Callable => "callable", | ||
169 | HlMod::Consuming => "consuming", | ||
166 | HlMod::ControlFlow => "control", | 170 | HlMod::ControlFlow => "control", |
167 | HlMod::Definition => "declaration", | 171 | HlMod::Definition => "declaration", |
168 | HlMod::Documentation => "documentation", | 172 | HlMod::Documentation => "documentation", |
169 | HlMod::Injected => "injected", | 173 | HlMod::Injected => "injected", |
174 | HlMod::IntraDocLink => "intra_doc_link", | ||
170 | HlMod::Mutable => "mutable", | 175 | HlMod::Mutable => "mutable", |
171 | HlMod::Consuming => "consuming", | ||
172 | HlMod::Unsafe => "unsafe", | ||
173 | HlMod::Callable => "callable", | ||
174 | HlMod::Static => "static", | 176 | HlMod::Static => "static", |
175 | HlMod::Associated => "associated", | 177 | HlMod::Unsafe => "unsafe", |
176 | } | 178 | } |
177 | } | 179 | } |
178 | 180 | ||
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html index 60c7518af..4635ea927 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html | |||
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .label { color: #DFAF8F; font-style: italic; } | 7 | .label { color: #DFAF8F; font-style: italic; } |
8 | .comment { color: #7F9F7F; } | 8 | .comment { color: #7F9F7F; } |
9 | .documentation { color: #629755; } | 9 | .documentation { color: #629755; } |
10 | .intra_doc_link { color: #A9C577; } | 10 | .intra_doc_link { font-style: italic; } |
11 | .injected { opacity: 0.65 ; } | 11 | .injected { opacity: 0.65 ; } |
12 | .struct, .enum { color: #7CB8BB; } | 12 | .struct, .enum { color: #7CB8BB; } |
13 | .enum_variant { color: #BDE0F3; } | 13 | .enum_variant { color: #BDE0F3; } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index 5d802a647..045162eb8 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html | |||
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .label { color: #DFAF8F; font-style: italic; } | 7 | .label { color: #DFAF8F; font-style: italic; } |
8 | .comment { color: #7F9F7F; } | 8 | .comment { color: #7F9F7F; } |
9 | .documentation { color: #629755; } | 9 | .documentation { color: #629755; } |
10 | .intra_doc_link { color: #A9C577; } | 10 | .intra_doc_link { font-style: italic; } |
11 | .injected { opacity: 0.65 ; } | 11 | .injected { opacity: 0.65 ; } |
12 | .struct, .enum { color: #7CB8BB; } | 12 | .struct, .enum { color: #7CB8BB; } |
13 | .enum_variant { color: #BDE0F3; } | 13 | .enum_variant { color: #BDE0F3; } |
@@ -99,8 +99,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
99 | <span class="brace">}</span> | 99 | <span class="brace">}</span> |
100 | <span class="brace">}</span> | 100 | <span class="brace">}</span> |
101 | 101 | ||
102 | <span class="comment documentation">/// </span><span class="intra_doc_link documentation">[`Foo`](Foo)</span><span class="comment documentation"> is a struct</span> | 102 | <span class="comment documentation">/// </span><span class="struct documentation intra_doc_link injected">[`Foo`](Foo)</span><span class="comment documentation"> is a struct</span> |
103 | <span class="comment documentation">/// </span><span class="intra_doc_link documentation">[`all_the_links`](all_the_links)</span><span class="comment documentation"> is this function</span> | 103 | <span class="comment documentation">/// </span><span class="function documentation intra_doc_link injected">[`all_the_links`](all_the_links)</span><span class="comment documentation"> is this function</span> |
104 | <span class="comment documentation">/// [`noop`](noop) is a macro below</span> | 104 | <span class="comment documentation">/// [`noop`](noop) is a macro below</span> |
105 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">all_the_links</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 105 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">all_the_links</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
106 | 106 | ||
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html index 4e312765c..ca9bb1e7d 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html | |||
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .label { color: #DFAF8F; font-style: italic; } | 7 | .label { color: #DFAF8F; font-style: italic; } |
8 | .comment { color: #7F9F7F; } | 8 | .comment { color: #7F9F7F; } |
9 | .documentation { color: #629755; } | 9 | .documentation { color: #629755; } |
10 | .intra_doc_link { color: #A9C577; } | 10 | .intra_doc_link { font-style: italic; } |
11 | .injected { opacity: 0.65 ; } | 11 | .injected { opacity: 0.65 ; } |
12 | .struct, .enum { color: #7CB8BB; } | 12 | .struct, .enum { color: #7CB8BB; } |
13 | .enum_variant { color: #BDE0F3; } | 13 | .enum_variant { color: #BDE0F3; } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html index 57dfe7509..9215ddd9e 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html | |||
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .label { color: #DFAF8F; font-style: italic; } | 7 | .label { color: #DFAF8F; font-style: italic; } |
8 | .comment { color: #7F9F7F; } | 8 | .comment { color: #7F9F7F; } |
9 | .documentation { color: #629755; } | 9 | .documentation { color: #629755; } |
10 | .intra_doc_link { color: #A9C577; } | 10 | .intra_doc_link { font-style: italic; } |
11 | .injected { opacity: 0.65 ; } | 11 | .injected { opacity: 0.65 ; } |
12 | .struct, .enum { color: #7CB8BB; } | 12 | .struct, .enum { color: #7CB8BB; } |
13 | .enum_variant { color: #BDE0F3; } | 13 | .enum_variant { color: #BDE0F3; } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index 75dbd0f14..e860d713e 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html | |||
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .label { color: #DFAF8F; font-style: italic; } | 7 | .label { color: #DFAF8F; font-style: italic; } |
8 | .comment { color: #7F9F7F; } | 8 | .comment { color: #7F9F7F; } |
9 | .documentation { color: #629755; } | 9 | .documentation { color: #629755; } |
10 | .intra_doc_link { color: #A9C577; } | 10 | .intra_doc_link { font-style: italic; } |
11 | .injected { opacity: 0.65 ; } | 11 | .injected { opacity: 0.65 ; } |
12 | .struct, .enum { color: #7CB8BB; } | 12 | .struct, .enum { color: #7CB8BB; } |
13 | .enum_variant { color: #BDE0F3; } | 13 | .enum_variant { color: #BDE0F3; } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html index 423256a20..6a6555208 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html | |||
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .label { color: #DFAF8F; font-style: italic; } | 7 | .label { color: #DFAF8F; font-style: italic; } |
8 | .comment { color: #7F9F7F; } | 8 | .comment { color: #7F9F7F; } |
9 | .documentation { color: #629755; } | 9 | .documentation { color: #629755; } |
10 | .intra_doc_link { color: #A9C577; } | 10 | .intra_doc_link { font-style: italic; } |
11 | .injected { opacity: 0.65 ; } | 11 | .injected { opacity: 0.65 ; } |
12 | .struct, .enum { color: #7CB8BB; } | 12 | .struct, .enum { color: #7CB8BB; } |
13 | .enum_variant { color: #BDE0F3; } | 13 | .enum_variant { color: #BDE0F3; } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index fffe8c0f5..8b2dd3b70 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html | |||
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .label { color: #DFAF8F; font-style: italic; } | 7 | .label { color: #DFAF8F; font-style: italic; } |
8 | .comment { color: #7F9F7F; } | 8 | .comment { color: #7F9F7F; } |
9 | .documentation { color: #629755; } | 9 | .documentation { color: #629755; } |
10 | .intra_doc_link { color: #A9C577; } | 10 | .intra_doc_link { font-style: italic; } |
11 | .injected { opacity: 0.65 ; } | 11 | .injected { opacity: 0.65 ; } |
12 | .struct, .enum { color: #7CB8BB; } | 12 | .struct, .enum { color: #7CB8BB; } |
13 | .enum_variant { color: #BDE0F3; } | 13 | .enum_variant { color: #BDE0F3; } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/injection.html b/crates/ide/src/syntax_highlighting/test_data/injection.html index 34d8deb68..9ab46d05c 100644 --- a/crates/ide/src/syntax_highlighting/test_data/injection.html +++ b/crates/ide/src/syntax_highlighting/test_data/injection.html | |||
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .label { color: #DFAF8F; font-style: italic; } | 7 | .label { color: #DFAF8F; font-style: italic; } |
8 | .comment { color: #7F9F7F; } | 8 | .comment { color: #7F9F7F; } |
9 | .documentation { color: #629755; } | 9 | .documentation { color: #629755; } |
10 | .intra_doc_link { color: #A9C577; } | 10 | .intra_doc_link { font-style: italic; } |
11 | .injected { opacity: 0.65 ; } | 11 | .injected { opacity: 0.65 ; } |
12 | .struct, .enum { color: #7CB8BB; } | 12 | .struct, .enum { color: #7CB8BB; } |
13 | .enum_variant { color: #BDE0F3; } | 13 | .enum_variant { color: #BDE0F3; } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html b/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html index d9ca3a4c4..666b0b228 100644 --- a/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html | |||
@@ -7,7 +7,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
7 | .label { color: #DFAF8F; font-style: italic; } | 7 | .label { color: #DFAF8F; font-style: italic; } |
8 | .comment { color: #7F9F7F; } | 8 | .comment { color: #7F9F7F; } |
9 | .documentation { color: #629755; } | 9 | .documentation { color: #629755; } |
10 | .intra_doc_link { color: #A9C577; } | 10 | .intra_doc_link { font-style: italic; } |
11 | .injected { opacity: 0.65 ; } | 11 | .injected { opacity: 0.65 ; } |
12 | .struct, .enum { color: #7CB8BB; } | 12 | .struct, .enum { color: #7CB8BB; } |
13 | .enum_variant { color: #BDE0F3; } | 13 | .enum_variant { color: #BDE0F3; } |
diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs index 3fa21ba7c..7578ad50b 100644 --- a/crates/ide_completion/src/render/macro_.rs +++ b/crates/ide_completion/src/render/macro_.rs | |||
@@ -91,7 +91,7 @@ impl<'a> MacroRender<'a> { | |||
91 | } | 91 | } |
92 | 92 | ||
93 | fn detail(&self) -> Option<String> { | 93 | fn detail(&self) -> Option<String> { |
94 | let ast_node = self.macro_.source(self.ctx.db())?.value; | 94 | let ast_node = self.macro_.source(self.ctx.db())?.value.left()?; |
95 | Some(macro_label(&ast_node)) | 95 | Some(macro_label(&ast_node)) |
96 | } | 96 | } |
97 | } | 97 | } |
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs index 0cb7d12a7..a3c5e9ccf 100644 --- a/crates/rust-analyzer/src/semantic_tokens.rs +++ b/crates/rust-analyzer/src/semantic_tokens.rs | |||
@@ -52,7 +52,6 @@ define_semantic_token_types![ | |||
52 | (ESCAPE_SEQUENCE, "escapeSequence"), | 52 | (ESCAPE_SEQUENCE, "escapeSequence"), |
53 | (FORMAT_SPECIFIER, "formatSpecifier"), | 53 | (FORMAT_SPECIFIER, "formatSpecifier"), |
54 | (GENERIC, "generic"), | 54 | (GENERIC, "generic"), |
55 | (INTRA_DOC_LINK, "intraDocLink"), | ||
56 | (LABEL, "label"), | 55 | (LABEL, "label"), |
57 | (LIFETIME, "lifetime"), | 56 | (LIFETIME, "lifetime"), |
58 | (PARENTHESIS, "parenthesis"), | 57 | (PARENTHESIS, "parenthesis"), |
@@ -90,6 +89,7 @@ define_semantic_token_modifiers![ | |||
90 | (UNSAFE, "unsafe"), | 89 | (UNSAFE, "unsafe"), |
91 | (ATTRIBUTE_MODIFIER, "attribute"), | 90 | (ATTRIBUTE_MODIFIER, "attribute"), |
92 | (CALLABLE, "callable"), | 91 | (CALLABLE, "callable"), |
92 | (INTRA_DOC_LINK, "intraDocLink"), | ||
93 | ]; | 93 | ]; |
94 | 94 | ||
95 | #[derive(Default)] | 95 | #[derive(Default)] |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 70501618e..1ddea9278 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -443,7 +443,6 @@ fn semantic_token_type_and_modifiers( | |||
443 | HlTag::Comment => lsp_types::SemanticTokenType::COMMENT, | 443 | HlTag::Comment => lsp_types::SemanticTokenType::COMMENT, |
444 | HlTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE, | 444 | HlTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE, |
445 | HlTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER, | 445 | HlTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER, |
446 | HlTag::IntraDocLink => semantic_tokens::INTRA_DOC_LINK, | ||
447 | HlTag::Keyword => lsp_types::SemanticTokenType::KEYWORD, | 446 | HlTag::Keyword => lsp_types::SemanticTokenType::KEYWORD, |
448 | HlTag::None => semantic_tokens::GENERIC, | 447 | HlTag::None => semantic_tokens::GENERIC, |
449 | HlTag::Operator => lsp_types::SemanticTokenType::OPERATOR, | 448 | HlTag::Operator => lsp_types::SemanticTokenType::OPERATOR, |
@@ -474,6 +473,7 @@ fn semantic_token_type_and_modifiers( | |||
474 | HlMod::Unsafe => semantic_tokens::UNSAFE, | 473 | HlMod::Unsafe => semantic_tokens::UNSAFE, |
475 | HlMod::Callable => semantic_tokens::CALLABLE, | 474 | HlMod::Callable => semantic_tokens::CALLABLE, |
476 | HlMod::Static => lsp_types::SemanticTokenModifier::STATIC, | 475 | HlMod::Static => lsp_types::SemanticTokenModifier::STATIC, |
476 | HlMod::IntraDocLink => semantic_tokens::INTRA_DOC_LINK, | ||
477 | HlMod::Associated => continue, | 477 | HlMod::Associated => continue, |
478 | }; | 478 | }; |
479 | mods |= modifier; | 479 | mods |= modifier; |
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index f4c37353c..dba2197de 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc | |||
@@ -384,11 +384,9 @@ If the LSP binary is not available, GNOME Builder can install it when opening a | |||
384 | 384 | ||
385 | === Eclipse IDE | 385 | === Eclipse IDE |
386 | 386 | ||
387 | Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. | ||
388 | |||
389 | Support for Rust development in the Eclipse IDE is provided by link:https://github.com/eclipse/corrosion[Eclipse Corrosion]. | 387 | Support for Rust development in the Eclipse IDE is provided by link:https://github.com/eclipse/corrosion[Eclipse Corrosion]. |
390 | While it currently uses RLS as default, you can successfully configure it so the IDE will use `rust-analyzer` instead. | 388 | If available in PATH or in some standard location, `rust-analyzer` is detected and powers editing of Rust files without further configuration. |
391 | To do so, with an Eclipse IDE where Corrosion is installed, just go to __Window > Preferences > Rust__ and edit the __Path to Rust Language Server__ entry to reference the path to `rust-analyzer`. | 389 | If `rust-analyzer` is not detected, Corrosion will prompt you for configuration of your Rust toolchain and language server with a link to the __Window > Preferences > Rust__ preference page; from here a button allows to download and configure `rust-analyzer`, but you can also reference another installation. |
392 | You'll need to close and reopen all .rs and Cargo files, or to restart the IDE, for this change to take effect. | 390 | You'll need to close and reopen all .rs and Cargo files, or to restart the IDE, for this change to take effect. |
393 | 391 | ||
394 | == Configuration | 392 | == Configuration |