auto merge of #12338 : edwardw/rust/hygienic-break-continue, r=cmr

Makes labelled loops hygiene by performing renaming of the labels defined in e.g. `'x: loop { ... }` and then used in break and continue statements within loop body so that they act hygienically when used with macros.
    
Closes #12262.
This commit is contained in:
bors 2014-02-23 15:37:05 -08:00
commit 329fcd48e5
18 changed files with 262 additions and 28 deletions

View file

@ -490,7 +490,7 @@ impl CFGBuilder {
fn find_scope(&self,
expr: @ast::Expr,
label: Option<ast::Name>) -> LoopScope {
label: Option<ast::Ident>) -> LoopScope {
match label {
None => {
return *self.loop_scopes.last().unwrap();

View file

@ -770,7 +770,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
fn find_scope<'a>(&self,
expr: &ast::Expr,
label: Option<ast::Name>,
label: Option<ast::Ident>,
loop_scopes: &'a mut ~[LoopScope]) -> &'a mut LoopScope {
let index = match label {
None => {

View file

@ -747,7 +747,7 @@ impl Liveness {
}
pub fn find_loop_scope(&self,
opt_label: Option<Name>,
opt_label: Option<Ident>,
id: NodeId,
sp: Span)
-> NodeId {

View file

@ -5206,13 +5206,13 @@ impl Resolver {
ExprLoop(_, Some(label)) => {
self.with_label_rib(|this| {
let def_like = DlDef(DefLabel(expr.id));
// plain insert (no renaming)
{
let mut label_ribs = this.label_ribs.borrow_mut();
let rib = label_ribs.get()[label_ribs.get().len() -
1];
let mut bindings = rib.bindings.borrow_mut();
bindings.get().insert(label.name, def_like);
let renamed = mtwt_resolve(label);
bindings.get().insert(renamed, def_like);
}
visit::walk_expr(this, expr, ());
@ -5223,11 +5223,12 @@ impl Resolver {
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
let mut label_ribs = self.label_ribs.borrow_mut();
match self.search_ribs(label_ribs.get(), label, expr.span) {
let renamed = mtwt_resolve(label);
match self.search_ribs(label_ribs.get(), renamed, expr.span) {
None =>
self.resolve_error(expr.span,
format!("use of undeclared label `{}`",
token::get_name(label))),
token::get_ident(label))),
Some(DlDef(def @ DefLabel(_))) => {
// Since this def is a label, it is never read.
self.record_def(expr.id, (def, LastMod(AllPublic)))

View file

@ -25,7 +25,7 @@ use util::ppaux::Repr;
use middle::trans::type_::Type;
use syntax::ast;
use syntax::ast::Name;
use syntax::ast::Ident;
use syntax::ast_util;
use syntax::codemap::Span;
use syntax::parse::token::InternedString;
@ -260,7 +260,7 @@ pub fn trans_loop<'a>(bcx:&'a Block<'a>,
pub fn trans_break_cont<'a>(bcx: &'a Block<'a>,
expr_id: ast::NodeId,
opt_label: Option<Name>,
opt_label: Option<Ident>,
exit: uint)
-> &'a Block<'a> {
let _icx = push_ctxt("trans_break_cont");
@ -293,14 +293,14 @@ pub fn trans_break_cont<'a>(bcx: &'a Block<'a>,
pub fn trans_break<'a>(bcx: &'a Block<'a>,
expr_id: ast::NodeId,
label_opt: Option<Name>)
label_opt: Option<Ident>)
-> &'a Block<'a> {
return trans_break_cont(bcx, expr_id, label_opt, cleanup::EXIT_BREAK);
}
pub fn trans_cont<'a>(bcx: &'a Block<'a>,
expr_id: ast::NodeId,
label_opt: Option<Name>)
label_opt: Option<Ident>)
-> &'a Block<'a> {
return trans_break_cont(bcx, expr_id, label_opt, cleanup::EXIT_LOOP);
}