Skip to content

Commit 7189c85

Browse files
committed
Improve closure dummy capture suggestion in macros.
1 parent 0a84708 commit 7189c85

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

compiler/rustc_typeck/src/check/upvar.rs

+26-9
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use rustc_middle::ty::{
4747
};
4848
use rustc_session::lint;
4949
use rustc_span::sym;
50-
use rustc_span::{BytePos, MultiSpan, Pos, Span, Symbol, DUMMY_SP};
50+
use rustc_span::{BytePos, MultiSpan, Pos, Span, Symbol};
5151
use rustc_trait_selection::infer::InferCtxtExt;
5252

5353
use rustc_data_structures::stable_map::FxHashMap;
@@ -680,15 +680,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
680680
migrated_variables_concat
681681
);
682682

683-
// If the body was entirely expanded from a macro
684-
// invocation, i.e. the body is not contained inside the
685-
// closure span, then we walk up the expansion until we
686-
// find the span before the expansion.
687-
let closure_body_span = self.tcx.hir().span(body_id.hir_id)
688-
.find_ancestor_inside(closure_span)
689-
.unwrap_or(DUMMY_SP);
683+
let mut closure_body_span = {
684+
// If the body was entirely expanded from a macro
685+
// invocation, i.e. the body is not contained inside the
686+
// closure span, then we walk up the expansion until we
687+
// find the span before the expansion.
688+
let s = self.tcx.hir().span(body_id.hir_id);
689+
s.find_ancestor_inside(closure_span).unwrap_or(s)
690+
};
691+
692+
if let Ok(mut s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
693+
if s.starts_with('$') {
694+
// Looks like a macro fragment. Try to find the real block.
695+
if let Some(hir::Node::Expr(&hir::Expr {
696+
kind: hir::ExprKind::Block(block, ..), ..
697+
})) = self.tcx.hir().find(body_id.hir_id) {
698+
// If the body is a block (with `{..}`), we use the span of that block.
699+
// E.g. with a `|| $body` expanded from a `m!({ .. })`, we use `{ .. }`, and not `$body`.
700+
// Since we know it's a block, we know we can insert the `let _ = ..` without
701+
// breaking the macro syntax.
702+
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(block.span) {
703+
closure_body_span = block.span;
704+
s = snippet;
705+
}
706+
}
707+
}
690708

691-
if let Ok(s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
692709
let mut lines = s.lines();
693710
let line1 = lines.next().unwrap_or_default();
694711

0 commit comments

Comments
 (0)