diff options
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 246 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 22 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 24 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 65 | ||||
-rw-r--r-- | crates/hir_def/src/path/lower.rs | 8 |
5 files changed, 217 insertions, 148 deletions
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/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 | ||
429 | macro_rules! impl_index { | 436 | macro_rules! impl_index { |
@@ -626,17 +633,22 @@ pub enum ModKind { | |||
626 | 633 | ||
627 | #[derive(Debug, Clone, Eq, PartialEq)] | 634 | #[derive(Debug, Clone, Eq, PartialEq)] |
628 | pub struct MacroCall { | 635 | pub 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)] | ||
642 | pub 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 2939c6b1e..b39d7fb7a 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -84,8 +84,7 @@ impl Ctx { | |||
84 | | ast::Item::Fn(_) | 84 | | ast::Item::Fn(_) |
85 | | ast::Item::TypeAlias(_) | 85 | | ast::Item::TypeAlias(_) |
86 | | ast::Item::Const(_) | 86 | | ast::Item::Const(_) |
87 | | ast::Item::Static(_) | 87 | | ast::Item::Static(_) => { |
88 | | ast::Item::MacroCall(_) => { | ||
89 | // 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 |
90 | // already. | 89 | // already. |
91 | if !inner { | 90 | if !inner { |
@@ -98,7 +97,11 @@ impl Ctx { | |||
98 | ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {} | 97 | ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {} |
99 | 98 | ||
100 | // These don't have inner items. | 99 | // These don't have inner items. |
101 | 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(_) => {} | ||
102 | }; | 105 | }; |
103 | 106 | ||
104 | let attrs = Attrs::new(item, &self.hygiene); | 107 | let attrs = Attrs::new(item, &self.hygiene); |
@@ -118,6 +121,7 @@ impl Ctx { | |||
118 | )), | 121 | )), |
119 | 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), |
120 | 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), | ||
121 | ast::Item::ExternBlock(ast) => { | 125 | ast::Item::ExternBlock(ast) => { |
122 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) | 126 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) |
123 | } | 127 | } |
@@ -525,9 +529,15 @@ impl Ctx { | |||
525 | } | 529 | } |
526 | 530 | ||
527 | 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>> { |
528 | let name = m.name().map(|it| it.as_name()); | ||
529 | let attrs = Attrs::new(m, &self.hygiene); | ||
530 | 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); | ||
531 | 541 | ||
532 | let ast_id = self.source_ast_id_map.ast_id(m); | 542 | let ast_id = self.source_ast_id_map.ast_id(m); |
533 | 543 | ||
@@ -547,8 +557,8 @@ impl Ctx { | |||
547 | }; | 557 | }; |
548 | 558 | ||
549 | let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); | 559 | let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); |
550 | 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 }; |
551 | Some(id(self.data().macro_calls.alloc(res))) | 561 | Some(id(self.data().macro_rules.alloc(res))) |
552 | } | 562 | } |
553 | 563 | ||
554 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { | 564 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { |
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(¯o_name); | 1279 | self.def_collector.resolve_proc_macro(¯o_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 | ||
1373 | fn is_macro_rules(path: &ModPath) -> bool { | ||
1374 | path.as_ident() == Some(&name![macro_rules]) | ||
1375 | } | ||
1376 | |||
1377 | #[cfg(test)] | 1368 | #[cfg(test)] |
1378 | mod tests { | 1369 | mod 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 | } |