aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-12-01 12:27:52 +0000
committerGitHub <[email protected]>2020-12-01 12:27:52 +0000
commiteb7f96951068bd8f8672a8234aa55b2a69d912b0 (patch)
tree30e949b7972420131a4367369c38b3bf2c5f66fa /crates/hir_def
parent75e037fcf75691a3a87d0cb37ea660dd7105ffba (diff)
parentea7b81fef990e281b4b958cff7357544076d4b15 (diff)
Merge #6683
6683: Emit macro diagnostics when lowering bodies r=matklad a=jonas-schievink Changes `Expander::enter_expand` to return an `ExpandResult`, and adds any contained errors to the body diagnostic list. Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/body.rs73
-rw-r--r--crates/hir_def/src/body/diagnostics.rs10
-rw-r--r--crates/hir_def/src/body/lower.rs31
-rw-r--r--crates/hir_def/src/data.rs2
4 files changed, 88 insertions, 28 deletions
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index d10b1af01..33eb5e78c 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -14,8 +14,8 @@ use cfg::CfgOptions;
14use drop_bomb::DropBomb; 14use drop_bomb::DropBomb;
15use either::Either; 15use either::Either;
16use hir_expand::{ 16use hir_expand::{
17 ast_id_map::AstIdMap, diagnostics::DiagnosticSink, hygiene::Hygiene, AstId, HirFileId, InFile, 17 ast_id_map::AstIdMap, diagnostics::DiagnosticSink, hygiene::Hygiene, AstId, ExpandResult,
18 MacroDefId, 18 HirFileId, InFile, MacroDefId,
19}; 19};
20use rustc_hash::FxHashMap; 20use rustc_hash::FxHashMap;
21use syntax::{ast, AstNode, AstPtr}; 21use syntax::{ast, AstNode, AstPtr};
@@ -102,11 +102,11 @@ impl Expander {
102 db: &dyn DefDatabase, 102 db: &dyn DefDatabase,
103 local_scope: Option<&ItemScope>, 103 local_scope: Option<&ItemScope>,
104 macro_call: ast::MacroCall, 104 macro_call: ast::MacroCall,
105 ) -> Option<(Mark, T)> { 105 ) -> ExpandResult<Option<(Mark, T)>> {
106 self.recursion_limit += 1; 106 self.recursion_limit += 1;
107 if self.recursion_limit > EXPANSION_RECURSION_LIMIT { 107 if self.recursion_limit > EXPANSION_RECURSION_LIMIT {
108 mark::hit!(your_stack_belongs_to_me); 108 mark::hit!(your_stack_belongs_to_me);
109 return None; 109 return ExpandResult::str_err("reached recursion limit during macro expansion".into());
110 } 110 }
111 111
112 let macro_call = InFile::new(self.current_file_id, &macro_call); 112 let macro_call = InFile::new(self.current_file_id, &macro_call);
@@ -120,28 +120,55 @@ impl Expander {
120 self.resolve_path_as_macro(db, &path) 120 self.resolve_path_as_macro(db, &path)
121 }; 121 };
122 122
123 if let Some(call_id) = macro_call.as_call_id(db, self.crate_def_map.krate, resolver) { 123 let call_id = match macro_call.as_call_id(db, self.crate_def_map.krate, resolver) {
124 let file_id = call_id.as_file(); 124 Some(it) => it,
125 if let Some(node) = db.parse_or_expand(file_id) { 125 None => {
126 if let Some(expr) = T::cast(node) { 126 // FIXME: this can mean other things too, but `as_call_id` doesn't provide enough
127 log::debug!("macro expansion {:#?}", expr.syntax()); 127 // info.
128 128 return ExpandResult::only_err(mbe::ExpandError::Other(
129 let mark = Mark { 129 "failed to parse or resolve macro invocation".into(),
130 file_id: self.current_file_id, 130 ));
131 ast_id_map: mem::take(&mut self.ast_id_map), 131 }
132 bomb: DropBomb::new("expansion mark dropped"), 132 };
133 }; 133
134 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); 134 let err = db.macro_expand_error(call_id);
135 self.current_file_id = file_id; 135
136 self.ast_id_map = db.ast_id_map(file_id); 136 let file_id = call_id.as_file();
137 return Some((mark, expr)); 137
138 let raw_node = match db.parse_or_expand(file_id) {
139 Some(it) => it,
140 None => {
141 // Only `None` if the macro expansion produced no usable AST.
142 if err.is_none() {
143 log::warn!("no error despite `parse_or_expand` failing");
138 } 144 }
145
146 return ExpandResult::only_err(err.unwrap_or_else(|| {
147 mbe::ExpandError::Other("failed to parse macro invocation".into())
148 }));
139 } 149 }
140 } 150 };
151
152 let node = match T::cast(raw_node) {
153 Some(it) => it,
154 None => {
155 // This can happen without being an error, so only forward previous errors.
156 return ExpandResult { value: None, err };
157 }
158 };
159
160 log::debug!("macro expansion {:#?}", node.syntax());
161
162 let mark = Mark {
163 file_id: self.current_file_id,
164 ast_id_map: mem::take(&mut self.ast_id_map),
165 bomb: DropBomb::new("expansion mark dropped"),
166 };
167 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
168 self.current_file_id = file_id;
169 self.ast_id_map = db.ast_id_map(file_id);
141 170
142 // FIXME: Instead of just dropping the error from expansion 171 ExpandResult { value: Some((mark, node)), err }
143 // report it
144 None
145 } 172 }
146 173
147 pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) { 174 pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
diff --git a/crates/hir_def/src/body/diagnostics.rs b/crates/hir_def/src/body/diagnostics.rs
index e57bdc133..1de7d30e2 100644
--- a/crates/hir_def/src/body/diagnostics.rs
+++ b/crates/hir_def/src/body/diagnostics.rs
@@ -2,11 +2,13 @@
2 2
3use hir_expand::diagnostics::DiagnosticSink; 3use hir_expand::diagnostics::DiagnosticSink;
4 4
5use crate::diagnostics::InactiveCode; 5use crate::diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro};
6 6
7#[derive(Debug, Eq, PartialEq)] 7#[derive(Debug, Eq, PartialEq)]
8pub(crate) enum BodyDiagnostic { 8pub(crate) enum BodyDiagnostic {
9 InactiveCode(InactiveCode), 9 InactiveCode(InactiveCode),
10 MacroError(MacroError),
11 UnresolvedProcMacro(UnresolvedProcMacro),
10} 12}
11 13
12impl BodyDiagnostic { 14impl BodyDiagnostic {
@@ -15,6 +17,12 @@ impl BodyDiagnostic {
15 BodyDiagnostic::InactiveCode(diag) => { 17 BodyDiagnostic::InactiveCode(diag) => {
16 sink.push(diag.clone()); 18 sink.push(diag.clone());
17 } 19 }
20 BodyDiagnostic::MacroError(diag) => {
21 sink.push(diag.clone());
22 }
23 BodyDiagnostic::UnresolvedProcMacro(diag) => {
24 sink.push(diag.clone());
25 }
18 } 26 }
19 } 27 }
20} 28}
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index cd7958746..2c41c0005 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -8,7 +8,7 @@ use either::Either;
8use hir_expand::{ 8use hir_expand::{
9 hygiene::Hygiene, 9 hygiene::Hygiene,
10 name::{name, AsName, Name}, 10 name::{name, AsName, Name},
11 HirFileId, MacroDefId, MacroDefKind, 11 ExpandError, HirFileId, MacroDefId, MacroDefKind,
12}; 12};
13use rustc_hash::FxHashMap; 13use rustc_hash::FxHashMap;
14use syntax::{ 14use syntax::{
@@ -25,7 +25,7 @@ use crate::{
25 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, 25 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax},
26 builtin_type::{BuiltinFloat, BuiltinInt}, 26 builtin_type::{BuiltinFloat, BuiltinInt},
27 db::DefDatabase, 27 db::DefDatabase,
28 diagnostics::InactiveCode, 28 diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro},
29 expr::{ 29 expr::{
30 dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, 30 dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal,
31 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 31 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
@@ -561,7 +561,32 @@ impl ExprCollector<'_> {
561 self.alloc_expr(Expr::Missing, syntax_ptr) 561 self.alloc_expr(Expr::Missing, syntax_ptr)
562 } else { 562 } else {
563 let macro_call = self.expander.to_source(AstPtr::new(&e)); 563 let macro_call = self.expander.to_source(AstPtr::new(&e));
564 match self.expander.enter_expand(self.db, Some(&self.body.item_scope), e) { 564 let res = self.expander.enter_expand(self.db, Some(&self.body.item_scope), e);
565
566 match res.err {
567 Some(ExpandError::UnresolvedProcMacro) => {
568 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro(
569 UnresolvedProcMacro {
570 file: self.expander.current_file_id,
571 node: syntax_ptr.clone().into(),
572 precise_location: None,
573 macro_name: None,
574 },
575 ));
576 }
577 Some(err) => {
578 self.source_map.diagnostics.push(BodyDiagnostic::MacroError(
579 MacroError {
580 file: self.expander.current_file_id,
581 node: syntax_ptr.clone().into(),
582 message: err.to_string(),
583 },
584 ));
585 }
586 None => {}
587 }
588
589 match res.value {
565 Some((mark, expansion)) => { 590 Some((mark, expansion)) => {
566 self.source_map 591 self.source_map
567 .expansions 592 .expansions
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index ff1ef0df6..146045938 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -257,7 +257,7 @@ fn collect_items(
257 let root = db.parse_or_expand(file_id).unwrap(); 257 let root = db.parse_or_expand(file_id).unwrap();
258 let call = ast_id_map.get(call.ast_id).to_node(&root); 258 let call = ast_id_map.get(call.ast_id).to_node(&root);
259 259
260 if let Some((mark, mac)) = expander.enter_expand(db, None, call) { 260 if let Some((mark, mac)) = expander.enter_expand(db, None, call).value {
261 let src: InFile<ast::MacroItems> = expander.to_source(mac); 261 let src: InFile<ast::MacroItems> = expander.to_source(mac);
262 let item_tree = db.item_tree(src.file_id); 262 let item_tree = db.item_tree(src.file_id);
263 let iter = 263 let iter =