Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 08f3752

Browse files
committedOct 8, 2015
hygiene for for loops, if let, while let
and some unrelated test cleanups
1 parent e0c7486 commit 08f3752

File tree

8 files changed

+94
-48
lines changed

8 files changed

+94
-48
lines changed
 

‎src/librustc/middle/region.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ impl RegionMaps {
377377
self.code_extents.borrow()[e.0 as usize]
378378
}
379379
pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(&CodeExtent, &CodeExtent) {
380-
for child_id in (1..self.code_extents.borrow().len()) {
380+
for child_id in 1..self.code_extents.borrow().len() {
381381
let child = CodeExtent(child_id as u32);
382382
if let Some(parent) = self.opt_encl_scope(child) {
383383
e(&child, &parent)

‎src/librustc_lint/unused.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -363,12 +363,10 @@ impl EarlyLintPass for UnusedParens {
363363
let (value, msg, struct_lit_needs_parens) = match e.node {
364364
ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true),
365365
ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true),
366-
ast::ExprMatch(ref head, _, source) => match source {
367-
ast::MatchSource::Normal => (head, "`match` head expression", true),
368-
ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true),
369-
ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true),
370-
ast::MatchSource::ForLoopDesugar => (head, "`for` head expression", true),
371-
},
366+
ast::ExprIfLet(_, ref cond, _, _) => (cond, "`if let` head expression", true),
367+
ast::ExprWhileLet(_, ref cond, _, _) => (cond, "`while let` head expression", true),
368+
ast::ExprForLoop(_, ref cond, _, _) => (cond, "`for` head expression", true),
369+
ast::ExprMatch(ref head, _, _) => (head, "`match` head expression", true),
372370
ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
373371
ast::ExprAssign(_, ref value) => (value, "assigned value", false),
374372
ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false),

‎src/librustc_typeck/check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1810,7 +1810,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18101810

18111811
// There is a possibility that this algorithm will have to run an arbitrary number of times
18121812
// to terminate so we bound it by the compiler's recursion limit.
1813-
for _ in (0..self.tcx().sess.recursion_limit.get()) {
1813+
for _ in 0..self.tcx().sess.recursion_limit.get() {
18141814
// First we try to solve all obligations, it is possible that the last iteration
18151815
// has made it possible to make more progress.
18161816
self.select_obligations_where_possible();

‎src/libsyntax/ext/expand.rs

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,18 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
8282
ast::ExprWhileLet(pat, expr, body, opt_ident) => {
8383
let pat = fld.fold_pat(pat);
8484
let expr = fld.fold_expr(expr);
85-
let (body, opt_ident) = expand_loop_block(body, opt_ident, fld);
86-
fld.cx.expr(span, ast::ExprWhileLet(pat, expr, body, opt_ident))
85+
86+
// Hygienic renaming of the body.
87+
let ((body, opt_ident), mut rewritten_pats) =
88+
rename_in_scope(vec![pat],
89+
fld,
90+
(body, opt_ident),
91+
|rename_fld, fld, (body, opt_ident)| {
92+
expand_loop_block(rename_fld.fold_block(body), opt_ident, fld)
93+
});
94+
assert!(rewritten_pats.len() == 1);
95+
96+
fld.cx.expr(span, ast::ExprWhileLet(rewritten_pats.remove(0), expr, body, opt_ident))
8797
}
8898

8999
ast::ExprLoop(loop_block, opt_ident) => {
@@ -93,9 +103,37 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
93103

94104
ast::ExprForLoop(pat, head, body, opt_ident) => {
95105
let pat = fld.fold_pat(pat);
106+
107+
// Hygienic renaming of the for loop body (for loop binds its pattern).
108+
let ((body, opt_ident), mut rewritten_pats) =
109+
rename_in_scope(vec![pat],
110+
fld,
111+
(body, opt_ident),
112+
|rename_fld, fld, (body, opt_ident)| {
113+
expand_loop_block(rename_fld.fold_block(body), opt_ident, fld)
114+
});
115+
assert!(rewritten_pats.len() == 1);
116+
96117
let head = fld.fold_expr(head);
97-
let (body, opt_ident) = expand_loop_block(body, opt_ident, fld);
98-
fld.cx.expr(span, ast::ExprForLoop(pat, head, body, opt_ident))
118+
fld.cx.expr(span, ast::ExprForLoop(rewritten_pats.remove(0), head, body, opt_ident))
119+
}
120+
121+
ast::ExprIfLet(pat, sub_expr, body, else_opt) => {
122+
let pat = fld.fold_pat(pat);
123+
124+
// Hygienic renaming of the body.
125+
let (body, mut rewritten_pats) =
126+
rename_in_scope(vec![pat],
127+
fld,
128+
body,
129+
|rename_fld, fld, body| {
130+
fld.fold_block(rename_fld.fold_block(body))
131+
});
132+
assert!(rewritten_pats.len() == 1);
133+
134+
let else_opt = else_opt.map(|else_opt| fld.fold_expr(else_opt));
135+
let sub_expr = fld.fold_expr(sub_expr);
136+
fld.cx.expr(span, ast::ExprIfLet(rewritten_pats.remove(0), sub_expr, body, else_opt))
99137
}
100138

101139
ast::ExprClosure(capture_clause, fn_decl, block) => {
@@ -569,18 +607,18 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
569607
if expanded_pats.is_empty() {
570608
panic!("encountered match arm with 0 patterns");
571609
}
572-
// all of the pats must have the same set of bindings, so use the
573-
// first one to extract them and generate new names:
574-
let idents = pattern_bindings(&*expanded_pats[0]);
575-
let new_renames = idents.into_iter().map(|id| (id, fresh_name(id))).collect();
576-
// apply the renaming, but only to the PatIdents:
577-
let mut rename_pats_fld = PatIdentRenamer{renames:&new_renames};
578-
let rewritten_pats = expanded_pats.move_map(|pat| rename_pats_fld.fold_pat(pat));
610+
579611
// apply renaming and then expansion to the guard and the body:
580-
let mut rename_fld = IdentRenamer{renames:&new_renames};
581-
let rewritten_guard =
582-
arm.guard.map(|g| fld.fold_expr(rename_fld.fold_expr(g)));
583-
let rewritten_body = fld.fold_expr(rename_fld.fold_expr(arm.body));
612+
let ((rewritten_guard, rewritten_body), rewritten_pats) =
613+
rename_in_scope(expanded_pats,
614+
fld,
615+
(arm.guard, arm.body),
616+
|rename_fld, fld, (ag, ab)|{
617+
let rewritten_guard = ag.map(|g| fld.fold_expr(rename_fld.fold_expr(g)));
618+
let rewritten_body = fld.fold_expr(rename_fld.fold_expr(ab));
619+
(rewritten_guard, rewritten_body)
620+
});
621+
584622
ast::Arm {
585623
attrs: fold::fold_attrs(arm.attrs, fld),
586624
pats: rewritten_pats,
@@ -589,6 +627,25 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
589627
}
590628
}
591629

630+
fn rename_in_scope<X, F>(pats: Vec<P<ast::Pat>>,
631+
fld: &mut MacroExpander,
632+
x: X,
633+
f: F)
634+
-> (X, Vec<P<ast::Pat>>)
635+
where F: Fn(&mut IdentRenamer, &mut MacroExpander, X) -> X
636+
{
637+
// all of the pats must have the same set of bindings, so use the
638+
// first one to extract them and generate new names:
639+
let idents = pattern_bindings(&*pats[0]);
640+
let new_renames = idents.into_iter().map(|id| (id, fresh_name(id))).collect();
641+
// apply the renaming, but only to the PatIdents:
642+
let mut rename_pats_fld = PatIdentRenamer{renames:&new_renames};
643+
let rewritten_pats = pats.move_map(|pat| rename_pats_fld.fold_pat(pat));
644+
645+
let mut rename_fld = IdentRenamer{ renames:&new_renames };
646+
(f(&mut rename_fld, fld, x), rewritten_pats)
647+
}
648+
592649
/// A visitor that extracts the PatIdent (binding) paths
593650
/// from a given thingy and puts them in a mutable
594651
/// array

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

Lines changed: 0 additions & 18 deletions
This file was deleted.

‎src/test/compile-fail/for-loop-refutable-pattern-error-message.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
for
13-
&1 //~ ERROR refutable pattern in `for` loop binding
14-
in [1].iter() {}
12+
for &1 in [1].iter() {} //~ ERROR refutable pattern in `for` loop binding
1513
}

‎src/test/compile-fail/issue-15167.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,17 @@ fn main() -> (){
1616
for n in 0..1 {
1717
println!("{}", f!()); //~ ERROR unresolved name `n`
1818
}
19+
20+
if let Some(n) = None {
21+
println!("{}", f!()); //~ ERROR unresolved name `n`
22+
}
23+
24+
if false {
25+
} else if let Some(n) = None {
26+
println!("{}", f!()); //~ ERROR unresolved name `n`
27+
}
28+
29+
while let Some(n) = None {
30+
println!("{}", f!()); //~ ERROR unresolved name `n`
31+
}
1932
}

‎src/test/compile-fail/issue-15381.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@
1313
fn main() {
1414
let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
1515

16-
for
17-
[x,y,z]
18-
//~^ ERROR refutable pattern in `for` loop binding: `[]` not covered
19-
in values.chunks(3).filter(|&xs| xs.len() == 3) {
16+
for [x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
17+
//~^ ERROR refutable pattern in `for` loop binding: `[]` not covered
2018
println!("y={}", y);
2119
}
2220
}

0 commit comments

Comments
 (0)
Please sign in to comment.