aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r--crates/hir_def/src/adt.rs13
-rw-r--r--crates/hir_def/src/body/lower.rs246
-rw-r--r--crates/hir_def/src/generics.rs55
-rw-r--r--crates/hir_def/src/item_tree.rs22
-rw-r--r--crates/hir_def/src/item_tree/lower.rs29
-rw-r--r--crates/hir_def/src/keys.rs5
-rw-r--r--crates/hir_def/src/nameres/collector.rs65
-rw-r--r--crates/hir_def/src/path/lower.rs8
-rw-r--r--crates/hir_def/src/src.rs5
9 files changed, 269 insertions, 179 deletions
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index 6539959c3..eafa3abb6 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -145,10 +145,12 @@ impl EnumData {
145 } 145 }
146} 146}
147 147
148impl HasChildSource for EnumId { 148impl HasChildSource<LocalEnumVariantId> for EnumId {
149 type ChildId = LocalEnumVariantId;
150 type Value = ast::Variant; 149 type Value = ast::Variant;
151 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { 150 fn child_source(
151 &self,
152 db: &dyn DefDatabase,
153 ) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> {
152 let src = self.lookup(db).source(db); 154 let src = self.lookup(db).source(db);
153 let mut trace = Trace::new_for_map(); 155 let mut trace = Trace::new_for_map();
154 lower_enum(db, &mut trace, &src, self.lookup(db).container.module(db)); 156 lower_enum(db, &mut trace, &src, self.lookup(db).container.module(db));
@@ -212,11 +214,10 @@ impl VariantData {
212 } 214 }
213} 215}
214 216
215impl HasChildSource for VariantId { 217impl HasChildSource<LocalFieldId> for VariantId {
216 type ChildId = LocalFieldId;
217 type Value = Either<ast::TupleField, ast::RecordField>; 218 type Value = Either<ast::TupleField, ast::RecordField>;
218 219
219 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { 220 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> {
220 let (src, module_id) = match self { 221 let (src, module_id) = match self {
221 VariantId::EnumVariantId(it) => { 222 VariantId::EnumVariantId(it) => {
222 // I don't really like the fact that we call into parent source 223 // I don't really like the fact that we call into parent source
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 689a3274c..bdba4c33e 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -548,63 +548,70 @@ impl ExprCollector<'_> {
548 } 548 }
549 } 549 }
550 ast::Expr::MacroCall(e) => { 550 ast::Expr::MacroCall(e) => {
551 if let Some(name) = e.is_macro_rules().map(|it| it.as_name()) { 551 let mut ids = vec![];
552 let mac = MacroDefId { 552 self.collect_macro_call(e, syntax_ptr.clone(), |this, expansion| {
553 krate: Some(self.expander.module.krate), 553 ids.push(match expansion {
554 ast_id: Some(self.expander.ast_id(&e)), 554 Some(it) => this.collect_expr(it),
555 kind: MacroDefKind::Declarative, 555 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
556 local_inner: false, 556 })
557 }; 557 });
558 self.body.item_scope.define_legacy_macro(name, mac); 558 ids[0]
559 }
560 }
561 }
559 562
560 // FIXME: do we still need to allocate this as missing ? 563 fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
561 self.alloc_expr(Expr::Missing, syntax_ptr) 564 &mut self,
565 e: ast::MacroCall,
566 syntax_ptr: AstPtr<ast::Expr>,
567 mut collector: F,
568 ) {
569 // File containing the macro call. Expansion errors will be attached here.
570 let outer_file = self.expander.current_file_id;
571
572 let macro_call = self.expander.to_source(AstPtr::new(&e));
573 let res = self.expander.enter_expand(self.db, Some(&self.body.item_scope), e);
574
575 match &res.err {
576 Some(ExpandError::UnresolvedProcMacro) => {
577 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro(
578 UnresolvedProcMacro {
579 file: outer_file,
580 node: syntax_ptr.into(),
581 precise_location: None,
582 macro_name: None,
583 },
584 ));
585 }
586 Some(err) => {
587 self.source_map.diagnostics.push(BodyDiagnostic::MacroError(MacroError {
588 file: outer_file,
589 node: syntax_ptr.into(),
590 message: err.to_string(),
591 }));
592 }
593 None => {}
594 }
595
596 match res.value {
597 Some((mark, expansion)) => {
598 // FIXME: Statements are too complicated to recover from error for now.
599 // It is because we don't have any hygenine for local variable expansion right now.
600 if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() {
601 self.expander.exit(self.db, mark);
602 collector(self, None);
562 } else { 603 } else {
563 // File containing the macro call. Expansion errors will be attached here. 604 self.source_map.expansions.insert(macro_call, self.expander.current_file_id);
564 let outer_file = self.expander.current_file_id;
565
566 let macro_call = self.expander.to_source(AstPtr::new(&e));
567 let res = self.expander.enter_expand(self.db, Some(&self.body.item_scope), e);
568
569 match res.err {
570 Some(ExpandError::UnresolvedProcMacro) => {
571 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro(
572 UnresolvedProcMacro {
573 file: outer_file,
574 node: syntax_ptr.clone().into(),
575 precise_location: None,
576 macro_name: None,
577 },
578 ));
579 }
580 Some(err) => {
581 self.source_map.diagnostics.push(BodyDiagnostic::MacroError(
582 MacroError {
583 file: outer_file,
584 node: syntax_ptr.clone().into(),
585 message: err.to_string(),
586 },
587 ));
588 }
589 None => {}
590 }
591 605
592 match res.value { 606 let item_tree = self.db.item_tree(self.expander.current_file_id);
593 Some((mark, expansion)) => { 607 self.item_trees.insert(self.expander.current_file_id, item_tree);
594 self.source_map 608
595 .expansions 609 let id = collector(self, Some(expansion));
596 .insert(macro_call, self.expander.current_file_id); 610 self.expander.exit(self.db, mark);
597 611 id
598 let item_tree = self.db.item_tree(self.expander.current_file_id);
599 self.item_trees.insert(self.expander.current_file_id, item_tree);
600 let id = self.collect_expr(expansion);
601 self.expander.exit(self.db, mark);
602 id
603 }
604 None => self.alloc_expr(Expr::Missing, syntax_ptr),
605 }
606 } 612 }
607 } 613 }
614 None => collector(self, None),
608 } 615 }
609 } 616 }
610 617
@@ -642,44 +649,75 @@ impl ExprCollector<'_> {
642 } 649 }
643 } 650 }
644 651
645 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { 652 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> {
646 let syntax_node_ptr = AstPtr::new(&block.clone().into()); 653 let stmt =
647 self.collect_block_items(&block); 654 match s {
648 let statements = block 655 ast::Stmt::LetStmt(stmt) => {
649 .statements() 656 self.check_cfg(&stmt)?;
650 .filter_map(|s| {
651 let stmt = match s {
652 ast::Stmt::LetStmt(stmt) => {
653 self.check_cfg(&stmt)?;
654
655 let pat = self.collect_pat_opt(stmt.pat());
656 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
657 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
658 Statement::Let { pat, type_ref, initializer }
659 }
660 ast::Stmt::ExprStmt(stmt) => {
661 self.check_cfg(&stmt)?;
662 657
663 Statement::Expr(self.collect_expr_opt(stmt.expr())) 658 let pat = self.collect_pat_opt(stmt.pat());
664 } 659 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
665 ast::Stmt::Item(item) => { 660 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
666 self.check_cfg(&item)?; 661 vec![Statement::Let { pat, type_ref, initializer }]
662 }
663 ast::Stmt::ExprStmt(stmt) => {
664 self.check_cfg(&stmt)?;
665
666 // Note that macro could be expended to multiple statements
667 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
668 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
669 let mut stmts = vec![];
670
671 self.collect_macro_call(m, syntax_ptr.clone(), |this, expansion| {
672 match expansion {
673 Some(expansion) => {
674 let statements: ast::MacroStmts = expansion;
675 this.collect_stmts_items(statements.statements());
667 676
668 return None; 677 statements.statements().for_each(|stmt| {
678 if let Some(mut r) = this.collect_stmt(stmt) {
679 stmts.append(&mut r);
680 }
681 });
682 if let Some(expr) = statements.expr() {
683 stmts.push(Statement::Expr(this.collect_expr(expr)));
684 }
685 }
686 None => {
687 stmts.push(Statement::Expr(
688 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
689 ));
690 }
691 }
692 });
693 stmts
694 } else {
695 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))]
669 } 696 }
670 }; 697 }
671 Some(stmt) 698 ast::Stmt::Item(item) => {
672 }) 699 self.check_cfg(&item)?;
673 .collect(); 700
701 return None;
702 }
703 };
704
705 Some(stmt)
706 }
707
708 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
709 let syntax_node_ptr = AstPtr::new(&block.clone().into());
710 self.collect_stmts_items(block.statements());
711 let statements =
712 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
674 let tail = block.expr().map(|e| self.collect_expr(e)); 713 let tail = block.expr().map(|e| self.collect_expr(e));
675 self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr) 714 self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr)
676 } 715 }
677 716
678 fn collect_block_items(&mut self, block: &ast::BlockExpr) { 717 fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) {
679 let container = ContainerId::DefWithBodyId(self.def); 718 let container = ContainerId::DefWithBodyId(self.def);
680 719
681 let items = block 720 let items = stmts
682 .statements()
683 .filter_map(|stmt| match stmt { 721 .filter_map(|stmt| match stmt {
684 ast::Stmt::Item(it) => Some(it), 722 ast::Stmt::Item(it) => Some(it),
685 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None, 723 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
@@ -733,26 +771,44 @@ impl ExprCollector<'_> {
733 | ast::Item::ExternCrate(_) 771 | ast::Item::ExternCrate(_)
734 | ast::Item::Module(_) 772 | ast::Item::Module(_)
735 | ast::Item::MacroCall(_) => return None, 773 | ast::Item::MacroCall(_) => return None,
774 ast::Item::MacroRules(def) => {
775 return Some(Either::Right(def));
776 }
736 }; 777 };
737 778
738 Some((def, name)) 779 Some(Either::Left((def, name)))
739 }) 780 })
740 .collect::<Vec<_>>(); 781 .collect::<Vec<_>>();
741 782
742 for (def, name) in items { 783 for either in items {
743 self.body.item_scope.define_def(def); 784 match either {
744 if let Some(name) = name { 785 Either::Left((def, name)) => {
745 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly 786 self.body.item_scope.define_def(def);
746 let has_constructor = match def { 787 if let Some(name) = name {
747 ModuleDefId::AdtId(AdtId::StructId(s)) => { 788 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
748 self.db.struct_data(s).variant_data.kind() != StructKind::Record 789 let has_constructor = match def {
790 ModuleDefId::AdtId(AdtId::StructId(s)) => {
791 self.db.struct_data(s).variant_data.kind() != StructKind::Record
792 }
793 _ => true,
794 };
795 self.body.item_scope.push_res(
796 name.as_name(),
797 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
798 );
749 } 799 }
750 _ => true, 800 }
751 }; 801 Either::Right(e) => {
752 self.body.item_scope.push_res( 802 let mac = MacroDefId {
753 name.as_name(), 803 krate: Some(self.expander.module.krate),
754 crate::per_ns::PerNs::from_def(def, vis, has_constructor), 804 ast_id: Some(self.expander.ast_id(&e)),
755 ); 805 kind: MacroDefKind::Declarative,
806 local_inner: false,
807 };
808 if let Some(name) = e.name() {
809 self.body.item_scope.define_legacy_macro(name.as_name(), mac);
810 }
811 }
756 } 812 }
757 } 813 }
758 } 814 }
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 5189c7e9f..924046435 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -19,10 +19,10 @@ use crate::{
19 db::DefDatabase, 19 db::DefDatabase,
20 dyn_map::DynMap, 20 dyn_map::DynMap,
21 keys, 21 keys,
22 src::HasChildSource, 22 src::{HasChildSource, HasSource},
23 src::HasSource,
24 type_ref::{LifetimeRef, TypeBound, TypeRef}, 23 type_ref::{LifetimeRef, TypeBound, TypeRef},
25 AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, 24 AdtId, GenericDefId, LifetimeParamId, LocalLifetimeParamId, LocalTypeParamId, Lookup,
25 TypeParamId,
26}; 26};
27 27
28/// Data about a generic parameter (to a function, struct, impl, ...). 28/// Data about a generic parameter (to a function, struct, impl, ...).
@@ -72,7 +72,11 @@ pub enum WherePredicateTypeTarget {
72 // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef) 72 // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef)
73} 73}
74 74
75type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>; 75#[derive(Default)]
76pub(crate) struct SourceMap {
77 pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>,
78 lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>,
79}
76 80
77impl GenericParams { 81impl GenericParams {
78 pub(crate) fn generic_params_query( 82 pub(crate) fn generic_params_query(
@@ -131,7 +135,7 @@ impl GenericParams {
131 135
132 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { 136 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
133 let mut generics = GenericParams::default(); 137 let mut generics = GenericParams::default();
134 let mut sm = ArenaMap::default(); 138 let mut sm = SourceMap::default();
135 139
136 // FIXME: add `: Sized` bound for everything except for `Self` in traits 140 // FIXME: add `: Sized` bound for everything except for `Self` in traits
137 let file_id = match def { 141 let file_id = match def {
@@ -174,7 +178,7 @@ impl GenericParams {
174 default: None, 178 default: None,
175 provenance: TypeParamProvenance::TraitSelf, 179 provenance: TypeParamProvenance::TraitSelf,
176 }); 180 });
177 sm.insert(self_param_id, Either::Left(src.value.clone())); 181 sm.type_params.insert(self_param_id, Either::Left(src.value.clone()));
178 // add super traits as bounds on Self 182 // add super traits as bounds on Self
179 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 183 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
180 let self_param = TypeRef::Path(name![Self].into()); 184 let self_param = TypeRef::Path(name![Self].into());
@@ -250,7 +254,7 @@ impl GenericParams {
250 provenance: TypeParamProvenance::TypeParamList, 254 provenance: TypeParamProvenance::TypeParamList,
251 }; 255 };
252 let param_id = self.types.alloc(param); 256 let param_id = self.types.alloc(param);
253 sm.insert(param_id, Either::Right(type_param.clone())); 257 sm.type_params.insert(param_id, Either::Right(type_param.clone()));
254 258
255 let type_ref = TypeRef::Path(name.into()); 259 let type_ref = TypeRef::Path(name.into());
256 self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref)); 260 self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref));
@@ -260,7 +264,8 @@ impl GenericParams {
260 .lifetime_token() 264 .lifetime_token()
261 .map_or_else(Name::missing, |tok| Name::new_lifetime(&tok)); 265 .map_or_else(Name::missing, |tok| Name::new_lifetime(&tok));
262 let param = LifetimeParamData { name: name.clone() }; 266 let param = LifetimeParamData { name: name.clone() };
263 let _param_id = self.lifetimes.alloc(param); 267 let param_id = self.lifetimes.alloc(param);
268 sm.lifetime_params.insert(param_id, lifetime_param.clone());
264 let lifetime_ref = LifetimeRef::new_name(name); 269 let lifetime_ref = LifetimeRef::new_name(name);
265 self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); 270 self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
266 } 271 }
@@ -341,26 +346,42 @@ impl GenericParams {
341 } 346 }
342} 347}
343 348
344impl HasChildSource for GenericDefId { 349impl HasChildSource<LocalTypeParamId> for GenericDefId {
345 type ChildId = LocalTypeParamId;
346 type Value = Either<ast::Trait, ast::TypeParam>; 350 type Value = Either<ast::Trait, ast::TypeParam>;
347 fn child_source(&self, db: &dyn DefDatabase) -> InFile<SourceMap> { 351 fn child_source(
348 let (_, sm) = GenericParams::new(db, *self); 352 &self,
349 sm 353 db: &dyn DefDatabase,
354 ) -> InFile<ArenaMap<LocalTypeParamId, Self::Value>> {
355 GenericParams::new(db, *self).1.map(|source_maps| source_maps.type_params)
356 }
357}
358
359impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
360 type Value = ast::LifetimeParam;
361 fn child_source(
362 &self,
363 db: &dyn DefDatabase,
364 ) -> InFile<ArenaMap<LocalLifetimeParamId, Self::Value>> {
365 GenericParams::new(db, *self).1.map(|source_maps| source_maps.lifetime_params)
350 } 366 }
351} 367}
352 368
353impl ChildBySource for GenericDefId { 369impl ChildBySource for GenericDefId {
354 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 370 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
355 let mut res = DynMap::default(); 371 let mut res = DynMap::default();
356 let arena_map = self.child_source(db); 372 let (_, sm) = GenericParams::new(db, *self);
357 let arena_map = arena_map.as_ref(); 373
358 for (local_id, src) in arena_map.value.iter() { 374 let sm = sm.as_ref();
375 for (local_id, src) in sm.value.type_params.iter() {
359 let id = TypeParamId { parent: *self, local_id }; 376 let id = TypeParamId { parent: *self, local_id };
360 if let Either::Right(type_param) = src { 377 if let Either::Right(type_param) = src {
361 res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id) 378 res[keys::TYPE_PARAM].insert(sm.with_value(type_param.clone()), id)
362 } 379 }
363 } 380 }
381 for (local_id, src) in sm.value.lifetime_params.iter() {
382 let id = LifetimeParamId { parent: *self, local_id };
383 res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id);
384 }
364 res 385 res
365 } 386 }
366} 387}
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index b08167281..1c9babf37 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -94,6 +94,9 @@ impl ItemTree {
94 ast::MacroItems(items) => { 94 ast::MacroItems(items) => {
95 ctx.lower_module_items(&items) 95 ctx.lower_module_items(&items)
96 }, 96 },
97 ast::MacroStmts(stmts) => {
98 ctx.lower_inner_items(stmts.syntax())
99 },
97 // Macros can expand to expressions. We return an empty item tree in this case, but 100 // Macros can expand to expressions. We return an empty item tree in this case, but
98 // still need to collect inner items. 101 // still need to collect inner items.
99 ast::Expr(e) => { 102 ast::Expr(e) => {
@@ -139,6 +142,7 @@ impl ItemTree {
139 type_aliases, 142 type_aliases,
140 mods, 143 mods,
141 macro_calls, 144 macro_calls,
145 macro_rules,
142 exprs, 146 exprs,
143 vis, 147 vis,
144 generics, 148 generics,
@@ -159,6 +163,7 @@ impl ItemTree {
159 type_aliases.shrink_to_fit(); 163 type_aliases.shrink_to_fit();
160 mods.shrink_to_fit(); 164 mods.shrink_to_fit();
161 macro_calls.shrink_to_fit(); 165 macro_calls.shrink_to_fit();
166 macro_rules.shrink_to_fit();
162 exprs.shrink_to_fit(); 167 exprs.shrink_to_fit();
163 168
164 vis.arena.shrink_to_fit(); 169 vis.arena.shrink_to_fit();
@@ -277,6 +282,7 @@ struct ItemTreeData {
277 type_aliases: Arena<TypeAlias>, 282 type_aliases: Arena<TypeAlias>,
278 mods: Arena<Mod>, 283 mods: Arena<Mod>,
279 macro_calls: Arena<MacroCall>, 284 macro_calls: Arena<MacroCall>,
285 macro_rules: Arena<MacroRules>,
280 exprs: Arena<Expr>, 286 exprs: Arena<Expr>,
281 287
282 vis: ItemVisibilities, 288 vis: ItemVisibilities,
@@ -424,6 +430,7 @@ mod_items! {
424 TypeAlias in type_aliases -> ast::TypeAlias, 430 TypeAlias in type_aliases -> ast::TypeAlias,
425 Mod in mods -> ast::Module, 431 Mod in mods -> ast::Module,
426 MacroCall in macro_calls -> ast::MacroCall, 432 MacroCall in macro_calls -> ast::MacroCall,
433 MacroRules in macro_rules -> ast::MacroRules,
427} 434}
428 435
429macro_rules! impl_index { 436macro_rules! impl_index {
@@ -626,17 +633,22 @@ pub enum ModKind {
626 633
627#[derive(Debug, Clone, Eq, PartialEq)] 634#[derive(Debug, Clone, Eq, PartialEq)]
628pub struct MacroCall { 635pub struct MacroCall {
629 /// For `macro_rules!` declarations, this is the name of the declared macro.
630 pub name: Option<Name>,
631 /// Path to the called macro. 636 /// Path to the called macro.
632 pub path: ModPath, 637 pub path: ModPath,
638 pub ast_id: FileAstId<ast::MacroCall>,
639}
640
641#[derive(Debug, Clone, Eq, PartialEq)]
642pub struct MacroRules {
643 /// For `macro_rules!` declarations, this is the name of the declared macro.
644 pub name: Name,
633 /// Has `#[macro_export]`. 645 /// Has `#[macro_export]`.
634 pub is_export: bool, 646 pub is_export: bool,
635 /// Has `#[macro_export(local_inner_macros)]`. 647 /// Has `#[macro_export(local_inner_macros)]`.
636 pub is_local_inner: bool, 648 pub is_local_inner: bool,
637 /// Has `#[rustc_builtin_macro]`. 649 /// Has `#[rustc_builtin_macro]`.
638 pub is_builtin: bool, 650 pub is_builtin: bool,
639 pub ast_id: FileAstId<ast::MacroCall>, 651 pub ast_id: FileAstId<ast::MacroRules>,
640} 652}
641 653
642// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array 654// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
@@ -667,7 +679,8 @@ impl ModItem {
667 | ModItem::Static(_) 679 | ModItem::Static(_)
668 | ModItem::Trait(_) 680 | ModItem::Trait(_)
669 | ModItem::Impl(_) 681 | ModItem::Impl(_)
670 | ModItem::Mod(_) => None, 682 | ModItem::Mod(_)
683 | ModItem::MacroRules(_) => None,
671 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), 684 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
672 ModItem::Const(konst) => Some(AssocItem::Const(*konst)), 685 ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
673 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), 686 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
@@ -694,6 +707,7 @@ impl ModItem {
694 ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(), 707 ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(),
695 ModItem::Mod(it) => tree[it.index].ast_id().upcast(), 708 ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
696 ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), 709 ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
710 ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
697 } 711 }
698 } 712 }
699} 713}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index f7ce2e26d..b39d7fb7a 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -2,7 +2,6 @@
2 2
3use std::{collections::hash_map::Entry, mem, sync::Arc}; 3use std::{collections::hash_map::Entry, mem, sync::Arc};
4 4
5use arena::map::ArenaMap;
6use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId}; 5use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId};
7use smallvec::SmallVec; 6use smallvec::SmallVec;
8use syntax::{ 7use syntax::{
@@ -85,8 +84,7 @@ impl Ctx {
85 | ast::Item::Fn(_) 84 | ast::Item::Fn(_)
86 | ast::Item::TypeAlias(_) 85 | ast::Item::TypeAlias(_)
87 | ast::Item::Const(_) 86 | ast::Item::Const(_)
88 | ast::Item::Static(_) 87 | ast::Item::Static(_) => {
89 | ast::Item::MacroCall(_) => {
90 // Skip this if we're already collecting inner items. We'll descend into all nodes 88 // Skip this if we're already collecting inner items. We'll descend into all nodes
91 // already. 89 // already.
92 if !inner { 90 if !inner {
@@ -99,7 +97,11 @@ impl Ctx {
99 ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {} 97 ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {}
100 98
101 // These don't have inner items. 99 // These don't have inner items.
102 ast::Item::Module(_) | ast::Item::ExternCrate(_) | ast::Item::Use(_) => {} 100 ast::Item::Module(_)
101 | ast::Item::ExternCrate(_)
102 | ast::Item::Use(_)
103 | ast::Item::MacroCall(_)
104 | ast::Item::MacroRules(_) => {}
103 }; 105 };
104 106
105 let attrs = Attrs::new(item, &self.hygiene); 107 let attrs = Attrs::new(item, &self.hygiene);
@@ -119,6 +121,7 @@ impl Ctx {
119 )), 121 )),
120 ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), 122 ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into),
121 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), 123 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
124 ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into),
122 ast::Item::ExternBlock(ast) => { 125 ast::Item::ExternBlock(ast) => {
123 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) 126 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
124 } 127 }
@@ -526,9 +529,15 @@ impl Ctx {
526 } 529 }
527 530
528 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { 531 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
529 let name = m.name().map(|it| it.as_name());
530 let attrs = Attrs::new(m, &self.hygiene);
531 let path = ModPath::from_src(m.path()?, &self.hygiene)?; 532 let path = ModPath::from_src(m.path()?, &self.hygiene)?;
533 let ast_id = self.source_ast_id_map.ast_id(m);
534 let res = MacroCall { path, ast_id };
535 Some(id(self.data().macro_calls.alloc(res)))
536 }
537
538 fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> {
539 let name = m.name().map(|it| it.as_name())?;
540 let attrs = Attrs::new(m, &self.hygiene);
532 541
533 let ast_id = self.source_ast_id_map.ast_id(m); 542 let ast_id = self.source_ast_id_map.ast_id(m);
534 543
@@ -548,8 +557,8 @@ impl Ctx {
548 }; 557 };
549 558
550 let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); 559 let is_builtin = attrs.by_key("rustc_builtin_macro").exists();
551 let res = MacroCall { name, path, is_export, is_builtin, is_local_inner, ast_id }; 560 let res = MacroRules { name, is_export, is_builtin, is_local_inner, ast_id };
552 Some(id(self.data().macro_calls.alloc(res))) 561 Some(id(self.data().macro_rules.alloc(res)))
553 } 562 }
554 563
555 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { 564 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
@@ -607,7 +616,7 @@ impl Ctx {
607 owner: GenericsOwner<'_>, 616 owner: GenericsOwner<'_>,
608 node: &impl ast::GenericParamsOwner, 617 node: &impl ast::GenericParamsOwner,
609 ) -> GenericParamsId { 618 ) -> GenericParamsId {
610 let mut sm = &mut ArenaMap::default(); 619 let mut sm = &mut Default::default();
611 let mut generics = GenericParams::default(); 620 let mut generics = GenericParams::default();
612 match owner { 621 match owner {
613 GenericsOwner::Function(func) => { 622 GenericsOwner::Function(func) => {
@@ -630,7 +639,7 @@ impl Ctx {
630 default: None, 639 default: None,
631 provenance: TypeParamProvenance::TraitSelf, 640 provenance: TypeParamProvenance::TraitSelf,
632 }); 641 });
633 sm.insert(self_param_id, Either::Left(trait_def.clone())); 642 sm.type_params.insert(self_param_id, Either::Left(trait_def.clone()));
634 // add super traits as bounds on Self 643 // add super traits as bounds on Self
635 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 644 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
636 let self_param = TypeRef::Path(name![Self].into()); 645 let self_param = TypeRef::Path(name![Self].into());
diff --git a/crates/hir_def/src/keys.rs b/crates/hir_def/src/keys.rs
index 40a5d92b5..9c585de2c 100644
--- a/crates/hir_def/src/keys.rs
+++ b/crates/hir_def/src/keys.rs
@@ -8,8 +8,8 @@ use syntax::{ast, AstNode, AstPtr};
8 8
9use crate::{ 9use crate::{
10 dyn_map::{DynMap, Policy}, 10 dyn_map::{DynMap, Policy},
11 ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, StaticId, StructId, TraitId, 11 ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId,
12 TypeAliasId, TypeParamId, UnionId, 12 StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
13}; 13};
14 14
15pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; 15pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
@@ -28,6 +28,7 @@ pub const VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
28pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new(); 28pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
29pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); 29pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); 30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
31pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
31 32
32pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); 33pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
33 34
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 19cd713ba..85cc342c4 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -11,7 +11,7 @@ use hir_expand::{
11 ast_id_map::FileAstId, 11 ast_id_map::FileAstId,
12 builtin_derive::find_builtin_derive, 12 builtin_derive::find_builtin_derive,
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{name, AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 HirFileId, MacroCallId, MacroDefId, MacroDefKind, 16 HirFileId, MacroCallId, MacroDefId, MacroDefKind,
17}; 17};
@@ -25,7 +25,9 @@ use crate::{
25 attr::Attrs, 25 attr::Attrs,
26 db::DefDatabase, 26 db::DefDatabase,
27 item_scope::{ImportType, PerNsGlobImports}, 27 item_scope::{ImportType, PerNsGlobImports},
28 item_tree::{self, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind}, 28 item_tree::{
29 self, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, StructDefKind,
30 },
29 nameres::{ 31 nameres::{
30 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 32 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
31 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, 33 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
@@ -972,7 +974,8 @@ impl ModCollector<'_, '_> {
972 status: PartialResolvedImport::Unresolved, 974 status: PartialResolvedImport::Unresolved,
973 }) 975 })
974 } 976 }
975 ModItem::MacroCall(mac) => self.collect_macro(&self.item_tree[mac]), 977 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
978 ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]),
976 ModItem::Impl(imp) => { 979 ModItem::Impl(imp) => {
977 let module = ModuleId { 980 let module = ModuleId {
978 krate: self.def_collector.def_map.krate, 981 krate: self.def_collector.def_map.krate,
@@ -1276,45 +1279,37 @@ impl ModCollector<'_, '_> {
1276 self.def_collector.resolve_proc_macro(&macro_name); 1279 self.def_collector.resolve_proc_macro(&macro_name);
1277 } 1280 }
1278 1281
1279 fn collect_macro(&mut self, mac: &MacroCall) { 1282 fn collect_macro_rules(&mut self, mac: &MacroRules) {
1280 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); 1283 let ast_id = InFile::new(self.file_id, mac.ast_id);
1281 1284
1282 // Case 0: builtin macros 1285 // Case 1: builtin macros
1283 if mac.is_builtin { 1286 if mac.is_builtin {
1284 if let Some(name) = &mac.name { 1287 let krate = self.def_collector.def_map.krate;
1285 let krate = self.def_collector.def_map.krate; 1288 if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) {
1286 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id.ast_id) {
1287 self.def_collector.define_macro(
1288 self.module_id,
1289 name.clone(),
1290 macro_id,
1291 mac.is_export,
1292 );
1293 return;
1294 }
1295 }
1296 }
1297
1298 // Case 1: macro rules, define a macro in crate-global mutable scope
1299 if is_macro_rules(&mac.path) {
1300 if let Some(name) = &mac.name {
1301 let macro_id = MacroDefId {
1302 ast_id: Some(ast_id.ast_id),
1303 krate: Some(self.def_collector.def_map.krate),
1304 kind: MacroDefKind::Declarative,
1305 local_inner: mac.is_local_inner,
1306 };
1307 self.def_collector.define_macro( 1289 self.def_collector.define_macro(
1308 self.module_id, 1290 self.module_id,
1309 name.clone(), 1291 mac.name.clone(),
1310 macro_id, 1292 macro_id,
1311 mac.is_export, 1293 mac.is_export,
1312 ); 1294 );
1295 return;
1313 } 1296 }
1314 return;
1315 } 1297 }
1316 1298
1317 // Case 2: try to resolve in legacy scope and expand macro_rules 1299 // Case 2: normal `macro_rules!` macro
1300 let macro_id = MacroDefId {
1301 ast_id: Some(ast_id),
1302 krate: Some(self.def_collector.def_map.krate),
1303 kind: MacroDefKind::Declarative,
1304 local_inner: mac.is_local_inner,
1305 };
1306 self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, mac.is_export);
1307 }
1308
1309 fn collect_macro_call(&mut self, mac: &MacroCall) {
1310 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone());
1311
1312 // Case 1: try to resolve in legacy scope and expand macro_rules
1318 if let Some(macro_call_id) = 1313 if let Some(macro_call_id) =
1319 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { 1314 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| {
1320 path.as_ident().and_then(|name| { 1315 path.as_ident().and_then(|name| {
@@ -1332,7 +1327,7 @@ impl ModCollector<'_, '_> {
1332 return; 1327 return;
1333 } 1328 }
1334 1329
1335 // Case 3: resolve in module scope, expand during name resolution. 1330 // Case 2: resolve in module scope, expand during name resolution.
1336 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. 1331 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
1337 if ast_id.path.is_ident() { 1332 if ast_id.path.is_ident() {
1338 ast_id.path.kind = PathKind::Super(0); 1333 ast_id.path.kind = PathKind::Super(0);
@@ -1370,10 +1365,6 @@ impl ModCollector<'_, '_> {
1370 } 1365 }
1371} 1366}
1372 1367
1373fn is_macro_rules(path: &ModPath) -> bool {
1374 path.as_ident() == Some(&name![macro_rules])
1375}
1376
1377#[cfg(test)] 1368#[cfg(test)]
1378mod tests { 1369mod tests {
1379 use crate::{db::DefDatabase, test_db::TestDB}; 1370 use crate::{db::DefDatabase, test_db::TestDB};
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index 60fa7646b..609925012 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -122,11 +122,9 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456
123 // We follow what it did anyway :) 123 // We follow what it did anyway :)
124 if segments.len() == 1 && kind == PathKind::Plain { 124 if segments.len() == 1 && kind == PathKind::Plain {
125 if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { 125 if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
126 if macro_call.is_bang() { 126 if let Some(crate_id) = hygiene.local_inner_macros() {
127 if let Some(crate_id) = hygiene.local_inner_macros() { 127 kind = PathKind::DollarCrate(crate_id);
128 kind = PathKind::DollarCrate(crate_id);
129 }
130 } 128 }
131 } 129 }
132 } 130 }
diff --git a/crates/hir_def/src/src.rs b/crates/hir_def/src/src.rs
index 7a79b0314..f67244b46 100644
--- a/crates/hir_def/src/src.rs
+++ b/crates/hir_def/src/src.rs
@@ -36,8 +36,7 @@ impl<N: ItemTreeNode> HasSource for ItemLoc<N> {
36 } 36 }
37} 37}
38 38
39pub trait HasChildSource { 39pub trait HasChildSource<ChildId> {
40 type ChildId;
41 type Value; 40 type Value;
42 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>>; 41 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<ChildId, Self::Value>>;
43} 42}