Skip to content

Commit ed44fe5

Browse files
committed
Auto merge of rust-lang#12668 - Veykril:mac-source-map, r=Veykril
fix: Simplify macro statement expansion handling I only meant to fix rust-lang/rust-analyzer#12644 but that somehow turned into a rewrite of the statement handling ... at least this fixes a few more issues in the IDE layer now
2 parents 8489cd7 + e5e5a09 commit ed44fe5

File tree

13 files changed

+221
-128
lines changed

13 files changed

+221
-128
lines changed

crates/hir-def/src/body.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use la_arena::{Arena, ArenaMap};
1919
use limit::Limit;
2020
use profile::Count;
2121
use rustc_hash::FxHashMap;
22-
use smallvec::SmallVec;
2322
use syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
2423

2524
use crate::{
@@ -294,10 +293,6 @@ pub struct BodySourceMap {
294293
field_map: FxHashMap<InFile<AstPtr<ast::RecordExprField>>, ExprId>,
295294
field_map_back: FxHashMap<ExprId, InFile<AstPtr<ast::RecordExprField>>>,
296295

297-
/// Maps a macro call to its lowered expressions, a single one if it expands to an expression,
298-
/// or multiple if it expands to MacroStmts.
299-
macro_call_to_exprs: FxHashMap<InFile<AstPtr<ast::MacroCall>>, SmallVec<[ExprId; 1]>>,
300-
301296
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
302297

303298
/// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in
@@ -466,9 +461,9 @@ impl BodySourceMap {
466461
self.field_map.get(&src).cloned()
467462
}
468463

469-
pub fn macro_expansion_expr(&self, node: InFile<&ast::MacroCall>) -> Option<&[ExprId]> {
470-
let src = node.map(AstPtr::new);
471-
self.macro_call_to_exprs.get(&src).map(|it| &**it)
464+
pub fn macro_expansion_expr(&self, node: InFile<&ast::MacroExpr>) -> Option<ExprId> {
465+
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::MacroExpr>).map(AstPtr::upcast);
466+
self.expr_map.get(&src).copied()
472467
}
473468

474469
/// Get a reference to the body source map's diagnostics.

crates/hir-def/src/body/lower.rs

Lines changed: 72 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use hir_expand::{
1313
use la_arena::Arena;
1414
use profile::Count;
1515
use rustc_hash::FxHashMap;
16-
use smallvec::smallvec;
1716
use syntax::{
1817
ast::{
1918
self, ArrayExprKind, AstChildren, HasArgList, HasLoopBody, HasName, LiteralKind,
@@ -97,7 +96,6 @@ pub(super) fn lower(
9796
or_pats: Default::default(),
9897
},
9998
expander,
100-
statements_in_scope: Vec::new(),
10199
name_to_pat_grouping: Default::default(),
102100
is_lowering_inside_or_pat: false,
103101
}
@@ -109,7 +107,6 @@ struct ExprCollector<'a> {
109107
expander: Expander,
110108
body: Body,
111109
source_map: BodySourceMap,
112-
statements_in_scope: Vec<Statement>,
113110
// a poor-mans union-find?
114111
name_to_pat_grouping: FxHashMap<Name, Vec<PatId>>,
115112
is_lowering_inside_or_pat: bool,
@@ -514,27 +511,25 @@ impl ExprCollector<'_> {
514511
ast::Expr::MacroExpr(e) => {
515512
let e = e.macro_call()?;
516513
let macro_ptr = AstPtr::new(&e);
517-
let id = self.collect_macro_call(e, macro_ptr.clone(), true, |this, expansion| {
514+
let id = self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
518515
expansion.map(|it| this.collect_expr(it))
519516
});
520517
match id {
521518
Some(id) => {
522-
self.source_map
523-
.macro_call_to_exprs
524-
.insert(self.expander.to_source(macro_ptr), smallvec![id]);
519+
// Make the macro-call point to its expanded expression so we can query
520+
// semantics on syntax pointers to the macro
521+
let src = self.expander.to_source(syntax_ptr);
522+
self.source_map.expr_map.insert(src, id);
525523
id
526524
}
527-
None => self.alloc_expr(Expr::Missing, syntax_ptr.clone()),
525+
None => self.alloc_expr(Expr::Missing, syntax_ptr),
528526
}
529527
}
530528
ast::Expr::MacroStmts(e) => {
531-
e.statements().for_each(|s| self.collect_stmt(s));
532-
let tail = e
533-
.expr()
534-
.map(|e| self.collect_expr(e))
535-
.unwrap_or_else(|| self.alloc_expr(Expr::Missing, syntax_ptr.clone()));
529+
let statements = e.statements().filter_map(|s| self.collect_stmt(s)).collect();
530+
let tail = e.expr().map(|e| self.collect_expr(e));
536531

537-
self.alloc_expr(Expr::MacroStmts { tail }, syntax_ptr)
532+
self.alloc_expr(Expr::MacroStmts { tail, statements }, syntax_ptr)
538533
}
539534
ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
540535
})
@@ -607,11 +602,11 @@ impl ExprCollector<'_> {
607602
}
608603
}
609604

610-
fn collect_stmt(&mut self, s: ast::Stmt) {
605+
fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Statement> {
611606
match s {
612607
ast::Stmt::LetStmt(stmt) => {
613608
if self.check_cfg(&stmt).is_none() {
614-
return;
609+
return None;
615610
}
616611
let pat = self.collect_pat_opt(stmt.pat());
617612
let type_ref =
@@ -621,70 +616,61 @@ impl ExprCollector<'_> {
621616
.let_else()
622617
.and_then(|let_else| let_else.block_expr())
623618
.map(|block| self.collect_block(block));
624-
self.statements_in_scope.push(Statement::Let {
625-
pat,
626-
type_ref,
627-
initializer,
628-
else_branch,
629-
});
619+
Some(Statement::Let { pat, type_ref, initializer, else_branch })
630620
}
631621
ast::Stmt::ExprStmt(stmt) => {
632-
if let Some(expr) = stmt.expr() {
633-
if self.check_cfg(&expr).is_none() {
634-
return;
622+
let expr = stmt.expr();
623+
if let Some(expr) = &expr {
624+
if self.check_cfg(expr).is_none() {
625+
return None;
635626
}
636627
}
637628
let has_semi = stmt.semicolon_token().is_some();
638-
// Note that macro could be expended to multiple statements
639-
if let Some(ast::Expr::MacroExpr(e)) = stmt.expr() {
640-
let m = match e.macro_call() {
641-
Some(it) => it,
642-
None => return,
643-
};
644-
let macro_ptr = AstPtr::new(&m);
645-
let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
646-
647-
let prev_stmt = self.statements_in_scope.len();
648-
self.collect_macro_call(m, macro_ptr.clone(), false, |this, expansion| {
649-
match expansion {
629+
// Note that macro could be expanded to multiple statements
630+
if let Some(expr @ ast::Expr::MacroExpr(mac)) = &expr {
631+
let mac_call = mac.macro_call()?;
632+
let syntax_ptr = AstPtr::new(expr);
633+
let macro_ptr = AstPtr::new(&mac_call);
634+
let stmt = self.collect_macro_call(
635+
mac_call,
636+
macro_ptr,
637+
false,
638+
|this, expansion: Option<ast::MacroStmts>| match expansion {
650639
Some(expansion) => {
651-
let statements: ast::MacroStmts = expansion;
652-
653-
statements.statements().for_each(|stmt| this.collect_stmt(stmt));
654-
if let Some(expr) = statements.expr() {
655-
let expr = this.collect_expr(expr);
656-
this.statements_in_scope
657-
.push(Statement::Expr { expr, has_semi });
658-
}
640+
let statements = expansion
641+
.statements()
642+
.filter_map(|stmt| this.collect_stmt(stmt))
643+
.collect();
644+
let tail = expansion.expr().map(|expr| this.collect_expr(expr));
645+
646+
let mac_stmts = this.alloc_expr(
647+
Expr::MacroStmts { tail, statements },
648+
AstPtr::new(&ast::Expr::MacroStmts(expansion)),
649+
);
650+
651+
Some(mac_stmts)
659652
}
660-
None => {
661-
let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
662-
this.statements_in_scope.push(Statement::Expr { expr, has_semi });
663-
}
664-
}
665-
});
653+
None => None,
654+
},
655+
);
666656

667-
let mut macro_exprs = smallvec![];
668-
for stmt in &self.statements_in_scope[prev_stmt..] {
669-
match *stmt {
670-
Statement::Let { initializer, else_branch, .. } => {
671-
macro_exprs.extend(initializer);
672-
macro_exprs.extend(else_branch);
673-
}
674-
Statement::Expr { expr, .. } => macro_exprs.push(expr),
657+
let expr = match stmt {
658+
Some(expr) => {
659+
// Make the macro-call point to its expanded expression so we can query
660+
// semantics on syntax pointers to the macro
661+
let src = self.expander.to_source(syntax_ptr);
662+
self.source_map.expr_map.insert(src, expr);
663+
expr
675664
}
676-
}
677-
if !macro_exprs.is_empty() {
678-
self.source_map
679-
.macro_call_to_exprs
680-
.insert(self.expander.to_source(macro_ptr), macro_exprs);
681-
}
665+
None => self.alloc_expr(Expr::Missing, syntax_ptr),
666+
};
667+
Some(Statement::Expr { expr, has_semi })
682668
} else {
683-
let expr = self.collect_expr_opt(stmt.expr());
684-
self.statements_in_scope.push(Statement::Expr { expr, has_semi });
669+
let expr = self.collect_expr_opt(expr);
670+
Some(Statement::Expr { expr, has_semi })
685671
}
686672
}
687-
ast::Stmt::Item(_item) => {}
673+
ast::Stmt::Item(_item) => None,
688674
}
689675
}
690676

@@ -703,25 +689,27 @@ impl ExprCollector<'_> {
703689
};
704690
let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
705691
let prev_local_module = mem::replace(&mut self.expander.module, module);
706-
let prev_statements = std::mem::take(&mut self.statements_in_scope);
707692

708-
block.statements().for_each(|s| self.collect_stmt(s));
709-
block.tail_expr().and_then(|e| {
710-
let expr = self.maybe_collect_expr(e)?;
711-
self.statements_in_scope.push(Statement::Expr { expr, has_semi: false });
712-
Some(())
693+
let mut statements: Vec<_> =
694+
block.statements().filter_map(|s| self.collect_stmt(s)).collect();
695+
let tail = block.tail_expr().and_then(|e| self.maybe_collect_expr(e));
696+
let tail = tail.or_else(|| {
697+
let stmt = statements.pop()?;
698+
if let Statement::Expr { expr, has_semi: false } = stmt {
699+
return Some(expr);
700+
}
701+
statements.push(stmt);
702+
None
713703
});
714704

715-
let mut tail = None;
716-
if let Some(Statement::Expr { expr, has_semi: false }) = self.statements_in_scope.last() {
717-
tail = Some(*expr);
718-
self.statements_in_scope.pop();
719-
}
720-
let tail = tail;
721-
let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements).into();
722705
let syntax_node_ptr = AstPtr::new(&block.into());
723706
let expr_id = self.alloc_expr(
724-
Expr::Block { id: block_id, statements, tail, label: None },
707+
Expr::Block {
708+
id: block_id,
709+
statements: statements.into_boxed_slice(),
710+
tail,
711+
label: None,
712+
},
725713
syntax_node_ptr,
726714
);
727715

@@ -903,10 +891,12 @@ impl ExprCollector<'_> {
903891
ast::Pat::MacroPat(mac) => match mac.macro_call() {
904892
Some(call) => {
905893
let macro_ptr = AstPtr::new(&call);
894+
let src = self.expander.to_source(Either::Left(AstPtr::new(&pat)));
906895
let pat =
907896
self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
908897
this.collect_pat_opt_(expanded_pat)
909898
});
899+
self.source_map.pat_map.insert(src, pat);
910900
return pat;
911901
}
912902
None => Pat::Missing,

crates/hir-def/src/body/scope.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -145,27 +145,28 @@ fn compute_block_scopes(
145145
tail: Option<ExprId>,
146146
body: &Body,
147147
scopes: &mut ExprScopes,
148-
mut scope: ScopeId,
148+
scope: &mut ScopeId,
149149
) {
150150
for stmt in statements {
151151
match stmt {
152152
Statement::Let { pat, initializer, else_branch, .. } => {
153153
if let Some(expr) = initializer {
154-
compute_expr_scopes(*expr, body, scopes, &mut scope);
154+
compute_expr_scopes(*expr, body, scopes, scope);
155155
}
156156
if let Some(expr) = else_branch {
157-
compute_expr_scopes(*expr, body, scopes, &mut scope);
157+
compute_expr_scopes(*expr, body, scopes, scope);
158158
}
159-
scope = scopes.new_scope(scope);
160-
scopes.add_bindings(body, scope, *pat);
159+
160+
*scope = scopes.new_scope(*scope);
161+
scopes.add_bindings(body, *scope, *pat);
161162
}
162163
Statement::Expr { expr, .. } => {
163-
compute_expr_scopes(*expr, body, scopes, &mut scope);
164+
compute_expr_scopes(*expr, body, scopes, scope);
164165
}
165166
}
166167
}
167168
if let Some(expr) = tail {
168-
compute_expr_scopes(expr, body, scopes, &mut scope);
169+
compute_expr_scopes(expr, body, scopes, scope);
169170
}
170171
}
171172

@@ -175,12 +176,15 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
175176

176177
scopes.set_scope(expr, *scope);
177178
match &body[expr] {
179+
Expr::MacroStmts { statements, tail } => {
180+
compute_block_scopes(statements, *tail, body, scopes, scope);
181+
}
178182
Expr::Block { statements, tail, id, label } => {
179-
let scope = scopes.new_block_scope(*scope, *id, make_label(label));
183+
let mut scope = scopes.new_block_scope(*scope, *id, make_label(label));
180184
// Overwrite the old scope for the block expr, so that every block scope can be found
181185
// via the block itself (important for blocks that only contain items, no expressions).
182186
scopes.set_scope(expr, scope);
183-
compute_block_scopes(statements, *tail, body, scopes, scope);
187+
compute_block_scopes(statements, *tail, body, scopes, &mut scope);
184188
}
185189
Expr::For { iterable, pat, body: body_expr, label } => {
186190
compute_expr_scopes(*iterable, body, scopes, scope);

crates/hir-def/src/expr.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,8 @@ pub enum Expr {
199199
body: ExprId,
200200
},
201201
MacroStmts {
202-
tail: ExprId,
202+
statements: Box<[Statement]>,
203+
tail: Option<ExprId>,
203204
},
204205
Array(Array),
205206
Literal(Literal),
@@ -254,7 +255,7 @@ impl Expr {
254255
Expr::Let { expr, .. } => {
255256
f(*expr);
256257
}
257-
Expr::Block { statements, tail, .. } => {
258+
Expr::MacroStmts { tail, statements } | Expr::Block { statements, tail, .. } => {
258259
for stmt in statements.iter() {
259260
match stmt {
260261
Statement::Let { initializer, .. } => {
@@ -344,7 +345,6 @@ impl Expr {
344345
f(*repeat)
345346
}
346347
},
347-
Expr::MacroStmts { tail } => f(*tail),
348348
Expr::Literal(_) => {}
349349
Expr::Underscore => {}
350350
}

crates/hir-ty/src/infer/expr.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,9 @@ impl<'a> InferenceContext<'a> {
774774
None => self.table.new_float_var(),
775775
},
776776
},
777-
Expr::MacroStmts { tail } => self.infer_expr_inner(*tail, expected),
777+
Expr::MacroStmts { tail, statements } => {
778+
self.infer_block(tgt_expr, statements, *tail, expected)
779+
}
778780
Expr::Underscore => {
779781
// Underscore expressions may only appear in assignee expressions,
780782
// which are handled by `infer_assignee_expr()`, so any underscore

0 commit comments

Comments
 (0)