mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
auto merge of #9103 : jbclements/rust/let-var-hygiene, r=erickt
update AST so that ExprBreak and ExprCont expressions contain names, not idents. Fixes #9047 and makes progress on #6993. Simplifies the compiler very slightly, should make it (infinitesimally) faster.
This commit is contained in:
commit
a9ac27270f
@ -488,7 +488,7 @@ impl CFGBuilder {
|
||||
|
||||
fn find_scope(&self,
|
||||
expr: @ast::Expr,
|
||||
label: Option<ast::Ident>) -> LoopScope {
|
||||
label: Option<ast::Name>) -> LoopScope {
|
||||
match label {
|
||||
None => {
|
||||
return *self.loop_scopes.last();
|
||||
|
@ -867,7 +867,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
|
||||
|
||||
fn find_scope<'a>(&self,
|
||||
expr: @ast::Expr,
|
||||
label: Option<ast::Ident>,
|
||||
label: Option<ast::Name>,
|
||||
loop_scopes: &'a mut ~[LoopScope]) -> &'a mut LoopScope {
|
||||
let index = match label {
|
||||
None => {
|
||||
|
@ -756,7 +756,7 @@ impl Liveness {
|
||||
}
|
||||
|
||||
pub fn find_loop_scope(&self,
|
||||
opt_label: Option<Ident>,
|
||||
opt_label: Option<Name>,
|
||||
id: NodeId,
|
||||
sp: Span)
|
||||
-> NodeId {
|
||||
|
@ -5157,15 +5157,13 @@ impl Resolver {
|
||||
ExprForLoop(*) => fail!("non-desugared expr_for_loop"),
|
||||
|
||||
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
|
||||
let name = label.name;
|
||||
match self.search_ribs(self.label_ribs, name, expr.span,
|
||||
match self.search_ribs(self.label_ribs, label, expr.span,
|
||||
DontAllowCapturingSelf) {
|
||||
None =>
|
||||
self.resolve_error(expr.span,
|
||||
fmt!("use of undeclared label \
|
||||
`%s`",
|
||||
self.session.str_of(
|
||||
label))),
|
||||
interner_get(label))),
|
||||
Some(DlDef(def @ DefLabel(_))) => {
|
||||
self.record_def(expr.id, def)
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ use std::vec;
|
||||
use std::local_data;
|
||||
use extra::time;
|
||||
use extra::sort;
|
||||
use syntax::ast::Ident;
|
||||
use syntax::ast::Name;
|
||||
use syntax::ast_map::{path, path_elt_to_str, path_name, path_pretty_name};
|
||||
use syntax::ast_util::{local_def};
|
||||
use syntax::attr;
|
||||
@ -1189,7 +1189,7 @@ pub fn scope_block(bcx: @mut Block,
|
||||
|
||||
pub fn loop_scope_block(bcx: @mut Block,
|
||||
loop_break: @mut Block,
|
||||
loop_label: Option<Ident>,
|
||||
loop_label: Option<Name>,
|
||||
n: &str,
|
||||
opt_node_info: Option<NodeInfo>) -> @mut Block {
|
||||
return new_block(bcx.fcx, Some(bcx), Some(@mut ScopeInfo {
|
||||
|
@ -38,7 +38,7 @@ use std::cast;
|
||||
use std::hashmap::{HashMap};
|
||||
use std::libc::{c_uint, c_longlong, c_ulonglong, c_char};
|
||||
use std::vec;
|
||||
use syntax::ast::Ident;
|
||||
use syntax::ast::{Name,Ident};
|
||||
use syntax::ast_map::{path, path_elt, path_pretty_name};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token;
|
||||
@ -463,7 +463,7 @@ pub fn block_cleanups(bcx: @mut Block) -> ~[cleanup] {
|
||||
pub struct ScopeInfo {
|
||||
parent: Option<@mut ScopeInfo>,
|
||||
loop_break: Option<@mut Block>,
|
||||
loop_label: Option<Ident>,
|
||||
loop_label: Option<Name>,
|
||||
// A list of functions that must be run at when leaving this
|
||||
// block, cleaning up any variables that were introduced in the
|
||||
// block.
|
||||
|
@ -22,7 +22,7 @@ use util::ppaux;
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::ast::Ident;
|
||||
use syntax::ast::Name;
|
||||
use syntax::ast_util;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
@ -188,7 +188,7 @@ pub fn trans_while(bcx: @mut Block, cond: @ast::Expr, body: &ast::Block) -> @mut
|
||||
|
||||
pub fn trans_loop(bcx:@mut Block,
|
||||
body: &ast::Block,
|
||||
opt_label: Option<Ident>)
|
||||
opt_label: Option<Name>)
|
||||
-> @mut Block {
|
||||
let _icx = push_ctxt("trans_loop");
|
||||
let next_bcx = sub_block(bcx, "next");
|
||||
@ -201,7 +201,7 @@ pub fn trans_loop(bcx:@mut Block,
|
||||
}
|
||||
|
||||
pub fn trans_break_cont(bcx: @mut Block,
|
||||
opt_label: Option<Ident>,
|
||||
opt_label: Option<Name>,
|
||||
to_end: bool)
|
||||
-> @mut Block {
|
||||
let _icx = push_ctxt("trans_break_cont");
|
||||
@ -254,11 +254,11 @@ pub fn trans_break_cont(bcx: @mut Block,
|
||||
return bcx;
|
||||
}
|
||||
|
||||
pub fn trans_break(bcx: @mut Block, label_opt: Option<Ident>) -> @mut Block {
|
||||
pub fn trans_break(bcx: @mut Block, label_opt: Option<Name>) -> @mut Block {
|
||||
return trans_break_cont(bcx, label_opt, true);
|
||||
}
|
||||
|
||||
pub fn trans_cont(bcx: @mut Block, label_opt: Option<Ident>) -> @mut Block {
|
||||
pub fn trans_cont(bcx: @mut Block, label_opt: Option<Name>) -> @mut Block {
|
||||
return trans_break_cont(bcx, label_opt, false);
|
||||
}
|
||||
|
||||
|
@ -617,7 +617,8 @@ fn trans_rvalue_stmt_unadjusted(bcx: @mut Block, expr: @ast::Expr) -> @mut Block
|
||||
return controlflow::trans_while(bcx, cond, body);
|
||||
}
|
||||
ast::ExprLoop(ref body, opt_label) => {
|
||||
return controlflow::trans_loop(bcx, body, opt_label);
|
||||
// FIXME #6993: map can go away when ast.rs is changed
|
||||
return controlflow::trans_loop(bcx, body, opt_label.map(|x| x.name));
|
||||
}
|
||||
ast::ExprAssign(dst, src) => {
|
||||
let src_datum = unpack_datum!(
|
||||
|
@ -522,10 +522,12 @@ pub enum Expr_ {
|
||||
ExprCast(@Expr, Ty),
|
||||
ExprIf(@Expr, Block, Option<@Expr>),
|
||||
ExprWhile(@Expr, Block),
|
||||
// FIXME #6993: change to Option<Name>
|
||||
ExprForLoop(@Pat, @Expr, Block, Option<Ident>),
|
||||
/* Conditionless loop (can be exited with break, cont, or ret)
|
||||
Same semantics as while(true) { body }, but typestate knows that the
|
||||
(implicit) condition is always true. */
|
||||
// FIXME #6993: change to Option<Name>
|
||||
ExprLoop(Block, Option<Ident>),
|
||||
ExprMatch(@Expr, ~[Arm]),
|
||||
ExprFnBlock(fn_decl, Block),
|
||||
@ -541,8 +543,8 @@ pub enum Expr_ {
|
||||
/// The special identifier `self`.
|
||||
ExprSelf,
|
||||
ExprAddrOf(Mutability, @Expr),
|
||||
ExprBreak(Option<Ident>),
|
||||
ExprAgain(Option<Ident>),
|
||||
ExprBreak(Option<Name>),
|
||||
ExprAgain(Option<Name>),
|
||||
ExprRet(Option<@Expr>),
|
||||
|
||||
/// Gets the log level for the enclosing module
|
||||
|
@ -113,6 +113,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
|
||||
|
||||
// Desugar expr_for_loop
|
||||
// From: `['<ident>:] for <src_pat> in <src_expr> <src_loop_block>`
|
||||
// FIXME #6993 : change type of opt_ident to Option<Name>
|
||||
ast::ExprForLoop(src_pat, src_expr, ref src_loop_block, opt_ident) => {
|
||||
// Expand any interior macros etc.
|
||||
// NB: we don't fold pats yet. Curious.
|
||||
@ -144,7 +145,8 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
|
||||
|
||||
// `None => break ['<ident>];`
|
||||
let none_arm = {
|
||||
let break_expr = cx.expr(span, ast::ExprBreak(opt_ident));
|
||||
// FIXME #6993: this map goes away:
|
||||
let break_expr = cx.expr(span, ast::ExprBreak(opt_ident.map(|x| x.name)));
|
||||
let none_pat = cx.pat_ident(span, none_ident);
|
||||
cx.arm(span, ~[none_pat], break_expr)
|
||||
};
|
||||
|
@ -688,10 +688,13 @@ pub fn noop_fold_expr(e: &Expr_, fld: @ast_fold) -> Expr_ {
|
||||
ExprPath(ref pth) => ExprPath(fld.fold_path(pth)),
|
||||
ExprSelf => ExprSelf,
|
||||
ExprBreak(ref opt_ident) => {
|
||||
ExprBreak(opt_ident.map_move(|x| fld.fold_ident(x)))
|
||||
// FIXME #6993: add fold_name to fold.... then cut out the
|
||||
// bogus Name->Ident->Name conversion.
|
||||
ExprBreak(opt_ident.map_move(|x| fld.fold_ident(Ident::new(x)).name))
|
||||
}
|
||||
ExprAgain(ref opt_ident) => {
|
||||
ExprAgain(opt_ident.map_move(|x| fld.fold_ident(x)))
|
||||
// FIXME #6993: add fold_name to fold....
|
||||
ExprAgain(opt_ident.map_move(|x| fld.fold_ident(Ident::new(x)).name))
|
||||
}
|
||||
ExprRet(ref e) => {
|
||||
ExprRet(e.map_move(|x| fld.fold_expr(x)))
|
||||
|
@ -1849,7 +1849,7 @@ impl Parser {
|
||||
if self.token_is_lifetime(&*self.token) {
|
||||
let lifetime = self.get_lifetime(&*self.token);
|
||||
self.bump();
|
||||
ex = ExprBreak(Some(lifetime));
|
||||
ex = ExprBreak(Some(lifetime.name));
|
||||
} else {
|
||||
ex = ExprBreak(None);
|
||||
}
|
||||
@ -2585,7 +2585,7 @@ impl Parser {
|
||||
let ex = if self.token_is_lifetime(&*self.token) {
|
||||
let lifetime = self.get_lifetime(&*self.token);
|
||||
self.bump();
|
||||
ExprAgain(Some(lifetime))
|
||||
ExprAgain(Some(lifetime.name))
|
||||
} else {
|
||||
ExprAgain(None)
|
||||
};
|
||||
|
@ -19,7 +19,7 @@ use codemap::{CodeMap, BytePos};
|
||||
use codemap;
|
||||
use diagnostic;
|
||||
use parse::classify::expr_is_simple_block;
|
||||
use parse::token::{ident_interner, ident_to_str};
|
||||
use parse::token::{ident_interner, ident_to_str, interner_get};
|
||||
use parse::{comments, token};
|
||||
use parse;
|
||||
use print::pp::{break_offset, word, space, zerobreak, hardbreak};
|
||||
@ -1394,7 +1394,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
|
||||
space(s.s);
|
||||
for ident in opt_ident.iter() {
|
||||
word(s.s, "'");
|
||||
print_ident(s, *ident);
|
||||
print_name(s, *ident);
|
||||
space(s.s);
|
||||
}
|
||||
}
|
||||
@ -1403,7 +1403,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
|
||||
space(s.s);
|
||||
for ident in opt_ident.iter() {
|
||||
word(s.s, "'");
|
||||
print_ident(s, *ident);
|
||||
print_name(s, *ident);
|
||||
space(s.s)
|
||||
}
|
||||
}
|
||||
@ -1503,6 +1503,10 @@ pub fn print_ident(s: @ps, ident: ast::Ident) {
|
||||
word(s.s, ident_to_str(&ident));
|
||||
}
|
||||
|
||||
pub fn print_name(s: @ps, name: ast::Name) {
|
||||
word(s.s, interner_get(name));
|
||||
}
|
||||
|
||||
pub fn print_for_decl(s: @ps, loc: &ast::Local, coll: &ast::Expr) {
|
||||
print_local_decl(s, loc);
|
||||
space(s.s);
|
||||
|
19
src/test/run-pass/issue-9047.rs
Normal file
19
src/test/run-pass/issue-9047.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
fn decode() -> ~str {
|
||||
'outer: loop {
|
||||
let mut ch_start: uint;
|
||||
break 'outer;
|
||||
}
|
||||
~""
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user