Skip to content

Commit eb4cb6d

Browse files
committed
Auto merge of #25318 - nrc:for-expn, r=sfackler
r? @sfackler
2 parents 67433c1 + edb2ee5 commit eb4cb6d

File tree

5 files changed

+89
-14
lines changed

5 files changed

+89
-14
lines changed

src/libsyntax/codemap.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,9 @@ pub enum MacroFormat {
235235
/// e.g. #[derive(...)] <item>
236236
MacroAttribute,
237237
/// e.g. `format!()`
238-
MacroBang
238+
MacroBang,
239+
/// Expansion performed by the compiler (libsyntax::expand).
240+
CompilerExpansion,
239241
}
240242

241243
#[derive(Clone, Hash, Debug)]

src/libsyntax/diagnostic.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -770,12 +770,15 @@ fn print_macro_backtrace(w: &mut EmitterWriter,
770770
|span| cm.span_to_string(span));
771771
let (pre, post) = match ei.callee.format {
772772
codemap::MacroAttribute => ("#[", "]"),
773-
codemap::MacroBang => ("", "!")
773+
codemap::MacroBang => ("", "!"),
774+
codemap::CompilerExpansion => ("", ""),
774775
};
775776
try!(print_diagnostic(w, &ss, Note,
776-
&format!("in expansion of {}{}{}", pre,
777-
ei.callee.name,
778-
post), None));
777+
&format!("in expansion of {}{}{}",
778+
pre,
779+
ei.callee.name,
780+
post),
781+
None));
779782
let ss = cm.span_to_string(ei.call_site);
780783
try!(print_diagnostic(w, &ss, Note, "expansion site", None));
781784
Ok(Some(ei.call_site))

src/libsyntax/ext/expand.rs

+42-9
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use ext::build::AstBuilder;
1919
use attr;
2020
use attr::AttrMetaMethods;
2121
use codemap;
22-
use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
22+
use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute, CompilerExpansion};
2323
use ext::base::*;
2424
use feature_gate::{self, Features};
2525
use fold;
@@ -34,6 +34,18 @@ use visit::Visitor;
3434
use std_inject;
3535

3636
pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
37+
fn push_compiler_expansion(fld: &mut MacroExpander, span: Span, expansion_desc: &str) {
38+
fld.cx.bt_push(ExpnInfo {
39+
call_site: span,
40+
callee: NameAndSpan {
41+
name: expansion_desc.to_string(),
42+
format: CompilerExpansion,
43+
allow_internal_unstable: true,
44+
span: None,
45+
},
46+
});
47+
}
48+
3749
e.and_then(|ast::Expr {id, node, span}| match node {
3850
// expr_mac should really be expr_ext or something; it's the
3951
// entry-point for all syntax extensions.
@@ -77,6 +89,8 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
7789
// }
7890
// }
7991

92+
push_compiler_expansion(fld, span, "while let expansion");
93+
8094
// `<pat> => <body>`
8195
let pat_arm = {
8296
let body_expr = fld.cx.expr_block(body);
@@ -98,7 +112,9 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
98112
// `[opt_ident]: loop { ... }`
99113
let loop_block = fld.cx.block_expr(match_expr);
100114
let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
101-
fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident))
115+
let result = fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident));
116+
fld.cx.bt_pop();
117+
result
102118
}
103119

104120
// Desugar ExprIfLet
@@ -112,6 +128,8 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
112128
// _ => [<elseopt> | ()]
113129
// }
114130

131+
push_compiler_expansion(fld, span, "if let expansion");
132+
115133
// `<pat> => <body>`
116134
let pat_arm = {
117135
let body_expr = fld.cx.expr_block(body);
@@ -173,13 +191,16 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
173191
ast::MatchSource::IfLetDesugar {
174192
contains_else_clause: contains_else_clause,
175193
}));
176-
fld.fold_expr(match_expr)
194+
let result = fld.fold_expr(match_expr);
195+
fld.cx.bt_pop();
196+
result
177197
}
178198

179199
// Desugar support for ExprIfLet in the ExprIf else position
180200
ast::ExprIf(cond, blk, elseopt) => {
181201
let elseopt = elseopt.map(|els| els.and_then(|els| match els.node {
182202
ast::ExprIfLet(..) => {
203+
push_compiler_expansion(fld, span, "if let expansion");
183204
// wrap the if-let expr in a block
184205
let span = els.span;
185206
let blk = P(ast::Block {
@@ -189,7 +210,9 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
189210
rules: ast::DefaultBlock,
190211
span: span
191212
});
192-
fld.cx.expr_block(blk)
213+
let result = fld.cx.expr_block(blk);
214+
fld.cx.bt_pop();
215+
result
193216
}
194217
_ => P(els)
195218
}));
@@ -221,6 +244,10 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
221244
// result
222245
// }
223246

247+
push_compiler_expansion(fld, span, "for loop expansion");
248+
249+
let span = fld.new_span(span);
250+
224251
// expand <head>
225252
let head = fld.fold_expr(head);
226253

@@ -235,10 +262,11 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
235262
rename_fld.fold_ident(ident)
236263
};
237264

238-
let pat_span = pat.span;
239-
// `:;std::option::Option::Some(<pat>) => <body>`
265+
let pat_span = fld.new_span(pat.span);
266+
// `::std::option::Option::Some(<pat>) => <body>`
240267
let pat_arm = {
241268
let body_expr = fld.cx.expr_block(body);
269+
let pat = noop_fold_pat(pat, fld);
242270
let some_pat = fld.cx.pat_some(pat_span, pat);
243271

244272
fld.cx.arm(pat_span, vec![some_pat], body_expr)
@@ -304,20 +332,25 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
304332

305333
// `{ let result = ...; result }`
306334
let result_ident = token::gensym_ident("result");
307-
fld.cx.expr_block(
335+
let result = fld.cx.expr_block(
308336
fld.cx.block_all(
309337
span,
310338
vec![fld.cx.stmt_let(span, false, result_ident, match_expr)],
311-
Some(fld.cx.expr_ident(span, result_ident))))
339+
Some(fld.cx.expr_ident(span, result_ident))));
340+
fld.cx.bt_pop();
341+
result
312342
}
313343

314344
ast::ExprClosure(capture_clause, fn_decl, block) => {
345+
push_compiler_expansion(fld, span, "closure expansion");
315346
let (rewritten_fn_decl, rewritten_block)
316347
= expand_and_rename_fn_decl_and_block(fn_decl, block, fld);
317348
let new_node = ast::ExprClosure(capture_clause,
318349
rewritten_fn_decl,
319350
rewritten_block);
320-
P(ast::Expr{id:id, node: new_node, span: fld.new_span(span)})
351+
let result = P(ast::Expr{id:id, node: new_node, span: fld.new_span(span)});
352+
fld.cx.bt_pop();
353+
result
321354
}
322355

323356
_ => {

src/test/compile-fail/for-expn-2.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we get an expansion stack for `for` loops.
12+
13+
// error-pattern:in expansion of for loop expansion
14+
15+
fn main() {
16+
for t in &foo {
17+
}
18+
}

src/test/compile-fail/for-expn.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that an error on a sub-expresson in a for loop has the correct span.
12+
13+
fn main() {
14+
// Odd formatting to make sure we get the right span.
15+
for t in &
16+
foo //~ ERROR unresolved name `foo`
17+
{
18+
}
19+
}

0 commit comments

Comments
 (0)