Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir_def/src/body/lower.rs')
-rw-r--r--crates/hir_def/src/body/lower.rs74
1 files changed, 46 insertions, 28 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 512a9312a7..d1cfc501e5 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -13,6 +13,7 @@ use hir_expand::{
use la_arena::Arena;
use profile::Count;
use rustc_hash::FxHashMap;
+use smallvec::smallvec;
use syntax::{
ast::{
self, ArrayExprKind, AstChildren, HasArgList, HasLoopBody, HasName, LiteralKind,
@@ -507,14 +508,18 @@ impl ExprCollector<'_> {
}
ast::Expr::MacroCall(e) => {
let macro_ptr = AstPtr::new(&e);
- let mut ids = None;
- self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
- ids.get_or_insert(match expansion {
- Some(it) => this.collect_expr(it),
- None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
- });
+ let id = self.collect_macro_call(e, macro_ptr.clone(), true, |this, expansion| {
+ expansion.map(|it| this.collect_expr(it))
});
- ids.unwrap_or_else(|| self.alloc_expr(Expr::Missing, syntax_ptr.clone()))
+ match id {
+ Some(id) => {
+ self.source_map
+ .macro_call_to_exprs
+ .insert(self.expander.to_source(macro_ptr), smallvec![id]);
+ id
+ }
+ None => self.alloc_expr(Expr::Missing, syntax_ptr.clone()),
+ }
}
ast::Expr::MacroStmts(e) => {
e.statements().for_each(|s| self.collect_stmt(s));
@@ -529,13 +534,17 @@ impl ExprCollector<'_> {
})
}
- fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
+ fn collect_macro_call<F, T, U>(
&mut self,
mcall: ast::MacroCall,
syntax_ptr: AstPtr<ast::MacroCall>,
record_diagnostics: bool,
- mut collector: F,
- ) {
+ collector: F,
+ ) -> U
+ where
+ F: FnOnce(&mut Self, Option<T>) -> U,
+ T: ast::AstNode,
+ {
// File containing the macro call. Expansion errors will be attached here.
let outer_file = self.expander.current_file_id;
@@ -551,8 +560,7 @@ impl ExprCollector<'_> {
path,
});
}
- collector(self, None);
- return;
+ return collector(self, None);
}
};
@@ -625,11 +633,9 @@ impl ExprCollector<'_> {
let macro_ptr = AstPtr::new(&m);
let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
- self.collect_macro_call(
- m,
- macro_ptr,
- false,
- |this, expansion| match expansion {
+ let prev_stmt = self.statements_in_scope.len();
+ self.collect_macro_call(m, macro_ptr.clone(), false, |this, expansion| {
+ match expansion {
Some(expansion) => {
let statements: ast::MacroStmts = expansion;
@@ -644,8 +650,24 @@ impl ExprCollector<'_> {
let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
this.statements_in_scope.push(Statement::Expr { expr, has_semi });
}
- },
- );
+ }
+ });
+
+ let mut macro_exprs = smallvec![];
+ for stmt in &self.statements_in_scope[prev_stmt..] {
+ match *stmt {
+ Statement::Let { initializer, else_branch, .. } => {
+ macro_exprs.extend(initializer);
+ macro_exprs.extend(else_branch);
+ }
+ Statement::Expr { expr, .. } => macro_exprs.push(expr),
+ }
+ }
+ if !macro_exprs.is_empty() {
+ self.source_map
+ .macro_call_to_exprs
+ .insert(self.expander.to_source(macro_ptr), macro_exprs);
+ }
} else {
let expr = self.collect_expr_opt(stmt.expr());
self.statements_in_scope.push(Statement::Expr { expr, has_semi });
@@ -870,15 +892,11 @@ impl ExprCollector<'_> {
ast::Pat::MacroPat(mac) => match mac.macro_call() {
Some(call) => {
let macro_ptr = AstPtr::new(&call);
- let mut pat = None;
- self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
- pat = Some(this.collect_pat_opt_(expanded_pat));
- });
-
- match pat {
- Some(pat) => return pat,
- None => Pat::Missing,
- }
+ let pat =
+ self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
+ this.collect_pat_opt_(expanded_pat)
+ });
+ return pat;
}
None => Pat::Missing,
},