mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-25 13:24:22 +00:00
Change expansion of for
loop to use a match
statement
so that the "innermost enclosing statement" used for rvalue temporaries matches up with user expectations
This commit is contained in:
parent
8f16356e5f
commit
b1da8c618f
@ -137,15 +137,16 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
|
||||
|
||||
// to:
|
||||
//
|
||||
// {
|
||||
// let _i = &mut <src_expr>;
|
||||
// ['<ident>:] loop {
|
||||
// match i.next() {
|
||||
// match &mut <src_expr> {
|
||||
// i => {
|
||||
// ['<ident>:] loop {
|
||||
// match i.next() {
|
||||
// None => break,
|
||||
// Some(<src_pat>) => <src_loop_block>
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
let local_ident = token::gensym_ident("i");
|
||||
let next_ident = fld.cx.ident_of("next");
|
||||
@ -154,10 +155,6 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
|
||||
let local_path = fld.cx.path_ident(span, local_ident);
|
||||
let some_path = fld.cx.path_ident(span, fld.cx.ident_of("Some"));
|
||||
|
||||
// `let i = &mut <src_expr>`
|
||||
let iter_decl_stmt = fld.cx.stmt_let(span, false, local_ident,
|
||||
fld.cx.expr_mut_addr_of(span, src_expr));
|
||||
|
||||
// `None => break ['<ident>];`
|
||||
let none_arm = {
|
||||
// FIXME #6993: this map goes away:
|
||||
@ -185,16 +182,13 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
|
||||
ast::ExprLoop(fld.cx.block_expr(match_expr),
|
||||
opt_ident));
|
||||
|
||||
// `{ let ... ; loop { ... } }`
|
||||
let block = fld.cx.block(span,
|
||||
~[iter_decl_stmt],
|
||||
Some(loop_expr));
|
||||
// `i => loop { ... }`
|
||||
|
||||
@ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
node: ast::ExprBlock(block),
|
||||
span: span,
|
||||
}
|
||||
// `match &mut <src_expr> { i => loop { ... } }`
|
||||
let discrim = fld.cx.expr_mut_addr_of(span, src_expr);
|
||||
let i_pattern = fld.cx.pat_ident(span, local_ident);
|
||||
let arm = fld.cx.arm(span, ~[i_pattern], loop_expr);
|
||||
fld.cx.expr_match(span, discrim, ~[arm])
|
||||
}
|
||||
|
||||
_ => noop_fold_expr(e, fld)
|
||||
|
70
src/test/run-pass/cleanup-rvalue-for-scope.rs
Normal file
70
src/test/run-pass/cleanup-rvalue-for-scope.rs
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that the lifetime of rvalues in for loops is extended
|
||||
// to the for loop itself.
|
||||
|
||||
#[feature(macro_rules)];
|
||||
|
||||
use std::ops::Drop;
|
||||
|
||||
static mut FLAGS: u64 = 0;
|
||||
|
||||
struct Box<T> { f: T }
|
||||
struct AddFlags { bits: u64 }
|
||||
|
||||
fn AddFlags(bits: u64) -> AddFlags {
|
||||
AddFlags { bits: bits }
|
||||
}
|
||||
|
||||
fn arg(exp: u64, _x: &AddFlags) {
|
||||
check_flags(exp);
|
||||
}
|
||||
|
||||
fn pass<T>(v: T) -> T {
|
||||
v
|
||||
}
|
||||
|
||||
fn check_flags(exp: u64) {
|
||||
unsafe {
|
||||
let x = FLAGS;
|
||||
FLAGS = 0;
|
||||
println!("flags {}, expected {}", x, exp);
|
||||
assert_eq!(x, exp);
|
||||
}
|
||||
}
|
||||
|
||||
impl AddFlags {
|
||||
fn check_flags<'a>(&'a self, exp: u64) -> &'a AddFlags {
|
||||
check_flags(exp);
|
||||
self
|
||||
}
|
||||
|
||||
fn bits(&self) -> u64 {
|
||||
self.bits
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for AddFlags {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
FLAGS = FLAGS + self.bits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
// The array containing [AddFlags] should not be dropped until
|
||||
// after the for loop:
|
||||
for x in [AddFlags(1)].iter() {
|
||||
check_flags(0);
|
||||
}
|
||||
check_flags(1);
|
||||
}
|
Loading…
Reference in New Issue
Block a user