librustc: Fix the issue with labels shadowing variable names by making
the leading quote part of the identifier for the purposes of hygiene. This adopts @jbclements' solution to #14539. I'm not sure if this is a breaking change or not. Closes #12512. [breaking-change]
This commit is contained in:
parent
e7f11f20e5
commit
2ed4734873
17 changed files with 159 additions and 89 deletions
|
@ -165,7 +165,7 @@ impl<'a, 'b> Visitor<Scope<'a>> for LifetimeContext<'b> {
|
||||||
fn visit_lifetime_ref(&mut self,
|
fn visit_lifetime_ref(&mut self,
|
||||||
lifetime_ref: &ast::Lifetime,
|
lifetime_ref: &ast::Lifetime,
|
||||||
scope: Scope<'a>) {
|
scope: Scope<'a>) {
|
||||||
if lifetime_ref.name == special_idents::statik.name {
|
if lifetime_ref.name == special_idents::static_lifetime.name {
|
||||||
self.insert_lifetime(lifetime_ref, DefStaticRegion);
|
self.insert_lifetime(lifetime_ref, DefStaticRegion);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ impl<'a> LifetimeContext<'a> {
|
||||||
lifetime_ref: &ast::Lifetime) {
|
lifetime_ref: &ast::Lifetime) {
|
||||||
self.sess.span_err(
|
self.sess.span_err(
|
||||||
lifetime_ref.span,
|
lifetime_ref.span,
|
||||||
format!("use of undeclared lifetime name `'{}`",
|
format!("use of undeclared lifetime name `{}`",
|
||||||
token::get_name(lifetime_ref.name)).as_slice());
|
token::get_name(lifetime_ref.name)).as_slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ impl<'a> LifetimeContext<'a> {
|
||||||
for i in range(0, lifetimes.len()) {
|
for i in range(0, lifetimes.len()) {
|
||||||
let lifetime_i = lifetimes.get(i);
|
let lifetime_i = lifetimes.get(i);
|
||||||
|
|
||||||
let special_idents = [special_idents::statik];
|
let special_idents = [special_idents::static_lifetime];
|
||||||
for lifetime in lifetimes.iter() {
|
for lifetime in lifetimes.iter() {
|
||||||
if special_idents.iter().any(|&i| i.name == lifetime.name) {
|
if special_idents.iter().any(|&i| i.name == lifetime.name) {
|
||||||
self.sess.span_err(
|
self.sess.span_err(
|
||||||
|
@ -354,7 +354,7 @@ impl<'a> LifetimeContext<'a> {
|
||||||
if lifetime_i.name == lifetime_j.name {
|
if lifetime_i.name == lifetime_j.name {
|
||||||
self.sess.span_err(
|
self.sess.span_err(
|
||||||
lifetime_j.span,
|
lifetime_j.span,
|
||||||
format!("lifetime name `'{}` declared twice in \
|
format!("lifetime name `{}` declared twice in \
|
||||||
the same scope",
|
the same scope",
|
||||||
token::get_name(lifetime_j.name)).as_slice());
|
token::get_name(lifetime_j.name)).as_slice());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1505,7 +1505,8 @@ impl LifeGiver {
|
||||||
fn give_lifetime(&self) -> ast::Lifetime {
|
fn give_lifetime(&self) -> ast::Lifetime {
|
||||||
let mut lifetime;
|
let mut lifetime;
|
||||||
loop {
|
loop {
|
||||||
let s = num_to_str(self.counter.get());
|
let mut s = String::from_str("'");
|
||||||
|
s.push_str(num_to_str(self.counter.get()).as_slice());
|
||||||
if !self.taken.contains(&s) {
|
if !self.taken.contains(&s) {
|
||||||
lifetime = name_to_dummy_lifetime(
|
lifetime = name_to_dummy_lifetime(
|
||||||
token::str_to_ident(s.as_slice()).name);
|
token::str_to_ident(s.as_slice()).name);
|
||||||
|
|
|
@ -162,7 +162,7 @@ pub fn bound_region_to_str(cx: &ctxt,
|
||||||
|
|
||||||
match br {
|
match br {
|
||||||
BrNamed(_, name) => {
|
BrNamed(_, name) => {
|
||||||
format!("{}'{}{}", prefix, token::get_name(name), space_str)
|
format!("{}{}{}", prefix, token::get_name(name), space_str)
|
||||||
}
|
}
|
||||||
BrAnon(_) => prefix.to_string(),
|
BrAnon(_) => prefix.to_string(),
|
||||||
BrFresh(_) => prefix.to_string(),
|
BrFresh(_) => prefix.to_string(),
|
||||||
|
|
|
@ -85,6 +85,7 @@ pub trait AstBuilder {
|
||||||
typ: P<ast::Ty>,
|
typ: P<ast::Ty>,
|
||||||
ex: Gc<ast::Expr>)
|
ex: Gc<ast::Expr>)
|
||||||
-> Gc<ast::Stmt>;
|
-> Gc<ast::Stmt>;
|
||||||
|
fn stmt_item(&self, sp: Span, item: Gc<ast::Item>) -> Gc<ast::Stmt>;
|
||||||
|
|
||||||
// blocks
|
// blocks
|
||||||
fn block(&self, span: Span, stmts: Vec<Gc<ast::Stmt>>,
|
fn block(&self, span: Span, stmts: Vec<Gc<ast::Stmt>>,
|
||||||
|
@ -239,6 +240,14 @@ pub trait AstBuilder {
|
||||||
vi: Vec<ast::ViewItem>,
|
vi: Vec<ast::ViewItem>,
|
||||||
items: Vec<Gc<ast::Item>>) -> Gc<ast::Item>;
|
items: Vec<Gc<ast::Item>>) -> Gc<ast::Item>;
|
||||||
|
|
||||||
|
fn item_static(&self,
|
||||||
|
span: Span,
|
||||||
|
name: Ident,
|
||||||
|
ty: P<ast::Ty>,
|
||||||
|
mutbl: ast::Mutability,
|
||||||
|
expr: Gc<ast::Expr>)
|
||||||
|
-> Gc<ast::Item>;
|
||||||
|
|
||||||
fn item_ty_poly(&self,
|
fn item_ty_poly(&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
name: Ident,
|
name: Ident,
|
||||||
|
@ -484,11 +493,19 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
box(GC) respan(sp, ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID))
|
box(GC) respan(sp, ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block(&self, span: Span, stmts: Vec<Gc<ast::Stmt>>,
|
fn block(&self,
|
||||||
expr: Option<Gc<Expr>>) -> P<ast::Block> {
|
span: Span,
|
||||||
|
stmts: Vec<Gc<ast::Stmt>>,
|
||||||
|
expr: Option<Gc<Expr>>)
|
||||||
|
-> P<ast::Block> {
|
||||||
self.block_all(span, Vec::new(), stmts, expr)
|
self.block_all(span, Vec::new(), stmts, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn stmt_item(&self, sp: Span, item: Gc<ast::Item>) -> Gc<ast::Stmt> {
|
||||||
|
let decl = respan(sp, ast::DeclItem(item));
|
||||||
|
box(GC) respan(sp, ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID))
|
||||||
|
}
|
||||||
|
|
||||||
fn block_expr(&self, expr: Gc<ast::Expr>) -> P<ast::Block> {
|
fn block_expr(&self, expr: Gc<ast::Expr>) -> P<ast::Block> {
|
||||||
self.block_all(expr.span, Vec::new(), Vec::new(), Some(expr))
|
self.block_all(expr.span, Vec::new(), Vec::new(), Some(expr))
|
||||||
}
|
}
|
||||||
|
@ -942,6 +959,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn item_static(&self,
|
||||||
|
span: Span,
|
||||||
|
name: Ident,
|
||||||
|
ty: P<ast::Ty>,
|
||||||
|
mutbl: ast::Mutability,
|
||||||
|
expr: Gc<ast::Expr>)
|
||||||
|
-> Gc<ast::Item> {
|
||||||
|
self.item(span, name, Vec::new(), ast::ItemStatic(ty, mutbl, expr))
|
||||||
|
}
|
||||||
|
|
||||||
fn item_ty_poly(&self, span: Span, name: Ident, ty: P<ast::Ty>,
|
fn item_ty_poly(&self, span: Span, name: Ident, ty: P<ast::Ty>,
|
||||||
generics: Generics) -> Gc<ast::Item> {
|
generics: Generics) -> Gc<ast::Item> {
|
||||||
self.item(span, name, Vec::new(), ast::ItemTy(ty, generics))
|
self.item(span, name, Vec::new(), ast::ItemTy(ty, generics))
|
||||||
|
|
|
@ -94,6 +94,18 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||||
}
|
}
|
||||||
|
|
||||||
let e = cx.expr_vec_slice(sp, bytes);
|
let e = cx.expr_vec_slice(sp, bytes);
|
||||||
let e = quote_expr!(cx, { static BYTES: &'static [u8] = $e; BYTES});
|
let ty = cx.ty(sp, ast::TyVec(cx.ty_ident(sp, cx.ident_of("u8"))));
|
||||||
|
let lifetime = cx.lifetime(sp, cx.ident_of("'static").name);
|
||||||
|
let item = cx.item_static(sp,
|
||||||
|
cx.ident_of("BYTES"),
|
||||||
|
cx.ty_rptr(sp,
|
||||||
|
ty,
|
||||||
|
Some(lifetime),
|
||||||
|
ast::MutImmutable),
|
||||||
|
ast::MutImmutable,
|
||||||
|
e);
|
||||||
|
let e = cx.expr_block(cx.block(sp,
|
||||||
|
vec!(cx.stmt_item(sp, item)),
|
||||||
|
Some(cx.expr_ident(sp, cx.ident_of("BYTES")))));
|
||||||
MacExpr::new(e)
|
MacExpr::new(e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||||
cx.ident_of("str")),
|
cx.ident_of("str")),
|
||||||
Some(cx.lifetime(sp,
|
Some(cx.lifetime(sp,
|
||||||
cx.ident_of(
|
cx.ident_of(
|
||||||
"static").name)),
|
"'static").name)),
|
||||||
ast::MutImmutable))))
|
ast::MutImmutable))))
|
||||||
}
|
}
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
|
|
|
@ -465,7 +465,7 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
self.ecx.ident_of("rt"),
|
self.ecx.ident_of("rt"),
|
||||||
self.ecx.ident_of("Piece")),
|
self.ecx.ident_of("Piece")),
|
||||||
vec!(self.ecx.lifetime(self.fmtsp,
|
vec!(self.ecx.lifetime(self.fmtsp,
|
||||||
self.ecx.ident_of("static").name)),
|
self.ecx.ident_of("'static").name)),
|
||||||
Vec::new()
|
Vec::new()
|
||||||
), None);
|
), None);
|
||||||
let ty = ast::TyFixedLengthVec(
|
let ty = ast::TyFixedLengthVec(
|
||||||
|
|
|
@ -757,19 +757,34 @@ impl<'a> StringReader<'a> {
|
||||||
while ident_continue(self.curr) {
|
while ident_continue(self.curr) {
|
||||||
self.bump();
|
self.bump();
|
||||||
}
|
}
|
||||||
let ident = self.with_str_from(start, |lifetime_name| {
|
|
||||||
str_to_ident(lifetime_name)
|
|
||||||
});
|
|
||||||
let tok = &token::IDENT(ident, false);
|
|
||||||
|
|
||||||
if token::is_keyword(token::keywords::Self, tok) {
|
// Include the leading `'` in the real identifier, for macro
|
||||||
self.err_span(start, self.last_pos,
|
// expansion purposes. See #12512 for the gory details of why
|
||||||
"invalid lifetime name: 'self \
|
// this is necessary.
|
||||||
is no longer a special lifetime");
|
let ident = self.with_str_from(start, |lifetime_name| {
|
||||||
} else if token::is_any_keyword(tok) &&
|
str_to_ident(format!("'{}", lifetime_name).as_slice())
|
||||||
!token::is_keyword(token::keywords::Static, tok) {
|
});
|
||||||
self.err_span(start, self.last_pos,
|
|
||||||
"invalid lifetime name");
|
// Conjure up a "keyword checking ident" to make sure that
|
||||||
|
// the lifetime name is not a keyword.
|
||||||
|
let keyword_checking_ident =
|
||||||
|
self.with_str_from(start, |lifetime_name| {
|
||||||
|
str_to_ident(lifetime_name)
|
||||||
|
});
|
||||||
|
let keyword_checking_token =
|
||||||
|
&token::IDENT(keyword_checking_ident, false);
|
||||||
|
if token::is_keyword(token::keywords::Self,
|
||||||
|
keyword_checking_token) {
|
||||||
|
self.err_span(start,
|
||||||
|
self.last_pos,
|
||||||
|
"invalid lifetime name: 'self \
|
||||||
|
is no longer a special lifetime");
|
||||||
|
} else if token::is_any_keyword(keyword_checking_token) &&
|
||||||
|
!token::is_keyword(token::keywords::Static,
|
||||||
|
keyword_checking_token) {
|
||||||
|
self.err_span(start,
|
||||||
|
self.last_pos,
|
||||||
|
"invalid lifetime name");
|
||||||
}
|
}
|
||||||
return token::LIFETIME(ident);
|
return token::LIFETIME(ident);
|
||||||
}
|
}
|
||||||
|
@ -1128,7 +1143,7 @@ mod test {
|
||||||
|
|
||||||
#[test] fn lifetime_name() {
|
#[test] fn lifetime_name() {
|
||||||
assert_eq!(setup(&mk_sh(), "'abc".to_string()).next_token().tok,
|
assert_eq!(setup(&mk_sh(), "'abc".to_string()).next_token().tok,
|
||||||
token::LIFETIME(token::str_to_ident("abc")));
|
token::LIFETIME(token::str_to_ident("'abc")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test] fn raw_string() {
|
#[test] fn raw_string() {
|
||||||
|
|
|
@ -3452,7 +3452,7 @@ impl<'a> Parser<'a> {
|
||||||
match self.token {
|
match self.token {
|
||||||
token::LIFETIME(lifetime) => {
|
token::LIFETIME(lifetime) => {
|
||||||
let lifetime_interned_string = token::get_ident(lifetime);
|
let lifetime_interned_string = token::get_ident(lifetime);
|
||||||
if lifetime_interned_string.equiv(&("static")) {
|
if lifetime_interned_string.equiv(&("'static")) {
|
||||||
result.push(StaticRegionTyParamBound);
|
result.push(StaticRegionTyParamBound);
|
||||||
if allow_any_lifetime && ret_lifetime.is_none() {
|
if allow_any_lifetime && ret_lifetime.is_none() {
|
||||||
ret_lifetime = Some(ast::Lifetime {
|
ret_lifetime = Some(ast::Lifetime {
|
||||||
|
|
|
@ -232,7 +232,7 @@ pub fn to_str(t: &Token) -> String {
|
||||||
/* Name components */
|
/* Name components */
|
||||||
IDENT(s, _) => get_ident(s).get().to_string(),
|
IDENT(s, _) => get_ident(s).get().to_string(),
|
||||||
LIFETIME(s) => {
|
LIFETIME(s) => {
|
||||||
(format!("'{}", get_ident(s))).to_string()
|
(format!("{}", get_ident(s))).to_string()
|
||||||
}
|
}
|
||||||
UNDERSCORE => "_".to_string(),
|
UNDERSCORE => "_".to_string(),
|
||||||
|
|
||||||
|
@ -433,71 +433,72 @@ declare_special_idents_and_keywords! {
|
||||||
(0, invalid, "");
|
(0, invalid, "");
|
||||||
(super::SELF_KEYWORD_NAME, self_, "self");
|
(super::SELF_KEYWORD_NAME, self_, "self");
|
||||||
(super::STATIC_KEYWORD_NAME, statik, "static");
|
(super::STATIC_KEYWORD_NAME, statik, "static");
|
||||||
|
(3, static_lifetime, "'static");
|
||||||
|
|
||||||
// for matcher NTs
|
// for matcher NTs
|
||||||
(3, tt, "tt");
|
(4, tt, "tt");
|
||||||
(4, matchers, "matchers");
|
(5, matchers, "matchers");
|
||||||
|
|
||||||
// outside of libsyntax
|
// outside of libsyntax
|
||||||
(5, clownshoe_abi, "__rust_abi");
|
(6, clownshoe_abi, "__rust_abi");
|
||||||
(6, opaque, "<opaque>");
|
(7, opaque, "<opaque>");
|
||||||
(7, unnamed_field, "<unnamed_field>");
|
(8, unnamed_field, "<unnamed_field>");
|
||||||
(8, type_self, "Self");
|
(9, type_self, "Self");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod keywords {
|
pub mod keywords {
|
||||||
// These ones are variants of the Keyword enum
|
// These ones are variants of the Keyword enum
|
||||||
|
|
||||||
'strict:
|
'strict:
|
||||||
(9, As, "as");
|
(10, As, "as");
|
||||||
(10, Break, "break");
|
(11, Break, "break");
|
||||||
(11, Crate, "crate");
|
(12, Crate, "crate");
|
||||||
(12, Else, "else");
|
(13, Else, "else");
|
||||||
(13, Enum, "enum");
|
(14, Enum, "enum");
|
||||||
(14, Extern, "extern");
|
(15, Extern, "extern");
|
||||||
(15, False, "false");
|
(16, False, "false");
|
||||||
(16, Fn, "fn");
|
(17, Fn, "fn");
|
||||||
(17, For, "for");
|
(18, For, "for");
|
||||||
(18, If, "if");
|
(19, If, "if");
|
||||||
(19, Impl, "impl");
|
(20, Impl, "impl");
|
||||||
(20, In, "in");
|
(21, In, "in");
|
||||||
(21, Let, "let");
|
(22, Let, "let");
|
||||||
(22, Loop, "loop");
|
(23, Loop, "loop");
|
||||||
(23, Match, "match");
|
(24, Match, "match");
|
||||||
(24, Mod, "mod");
|
(25, Mod, "mod");
|
||||||
(25, Mut, "mut");
|
(26, Mut, "mut");
|
||||||
(26, Once, "once");
|
(27, Once, "once");
|
||||||
(27, Pub, "pub");
|
(28, Pub, "pub");
|
||||||
(28, Ref, "ref");
|
(29, Ref, "ref");
|
||||||
(29, Return, "return");
|
(30, Return, "return");
|
||||||
// Static and Self are also special idents (prefill de-dupes)
|
// Static and Self are also special idents (prefill de-dupes)
|
||||||
(super::STATIC_KEYWORD_NAME, Static, "static");
|
(super::STATIC_KEYWORD_NAME, Static, "static");
|
||||||
(super::SELF_KEYWORD_NAME, Self, "self");
|
(super::SELF_KEYWORD_NAME, Self, "self");
|
||||||
(30, Struct, "struct");
|
(31, Struct, "struct");
|
||||||
(31, Super, "super");
|
(32, Super, "super");
|
||||||
(32, True, "true");
|
(33, True, "true");
|
||||||
(33, Trait, "trait");
|
(34, Trait, "trait");
|
||||||
(34, Type, "type");
|
(35, Type, "type");
|
||||||
(35, Unsafe, "unsafe");
|
(36, Unsafe, "unsafe");
|
||||||
(36, Use, "use");
|
(37, Use, "use");
|
||||||
(37, Virtual, "virtual");
|
(38, Virtual, "virtual");
|
||||||
(38, While, "while");
|
(39, While, "while");
|
||||||
(39, Continue, "continue");
|
(40, Continue, "continue");
|
||||||
(40, Proc, "proc");
|
(41, Proc, "proc");
|
||||||
(41, Box, "box");
|
(42, Box, "box");
|
||||||
|
|
||||||
'reserved:
|
'reserved:
|
||||||
(42, Alignof, "alignof");
|
(43, Alignof, "alignof");
|
||||||
(43, Be, "be");
|
(44, Be, "be");
|
||||||
(44, Const, "const");
|
(45, Const, "const");
|
||||||
(45, Offsetof, "offsetof");
|
(46, Offsetof, "offsetof");
|
||||||
(46, Priv, "priv");
|
(47, Priv, "priv");
|
||||||
(47, Pure, "pure");
|
(48, Pure, "pure");
|
||||||
(48, Sizeof, "sizeof");
|
(49, Sizeof, "sizeof");
|
||||||
(49, Typeof, "typeof");
|
(50, Typeof, "typeof");
|
||||||
(50, Unsized, "unsized");
|
(51, Unsized, "unsized");
|
||||||
(51, Yield, "yield");
|
(52, Yield, "yield");
|
||||||
(52, Do, "do");
|
(53, Do, "do");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use abi;
|
use abi;
|
||||||
use ast::{P, StaticRegionTyParamBound, OtherRegionTyParamBound,
|
use ast::{P, StaticRegionTyParamBound, OtherRegionTyParamBound};
|
||||||
TraitTyParamBound, UnboxedFnTyParamBound, Required, Provided};
|
use ast::{TraitTyParamBound, UnboxedFnTyParamBound, Required, Provided};
|
||||||
use ast;
|
use ast;
|
||||||
use ast_util;
|
use ast_util;
|
||||||
use owned_slice::OwnedSlice;
|
use owned_slice::OwnedSlice;
|
||||||
|
@ -1325,7 +1325,6 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::ExprForLoop(ref pat, ref iter, ref blk, opt_ident) => {
|
ast::ExprForLoop(ref pat, ref iter, ref blk, opt_ident) => {
|
||||||
for ident in opt_ident.iter() {
|
for ident in opt_ident.iter() {
|
||||||
try!(word(&mut self.s, "'"));
|
|
||||||
try!(self.print_ident(*ident));
|
try!(self.print_ident(*ident));
|
||||||
try!(self.word_space(":"));
|
try!(self.word_space(":"));
|
||||||
}
|
}
|
||||||
|
@ -1339,7 +1338,6 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::ExprLoop(ref blk, opt_ident) => {
|
ast::ExprLoop(ref blk, opt_ident) => {
|
||||||
for ident in opt_ident.iter() {
|
for ident in opt_ident.iter() {
|
||||||
try!(word(&mut self.s, "'"));
|
|
||||||
try!(self.print_ident(*ident));
|
try!(self.print_ident(*ident));
|
||||||
try!(self.word_space(":"));
|
try!(self.word_space(":"));
|
||||||
}
|
}
|
||||||
|
@ -1504,7 +1502,6 @@ impl<'a> State<'a> {
|
||||||
try!(word(&mut self.s, "break"));
|
try!(word(&mut self.s, "break"));
|
||||||
try!(space(&mut self.s));
|
try!(space(&mut self.s));
|
||||||
for ident in opt_ident.iter() {
|
for ident in opt_ident.iter() {
|
||||||
try!(word(&mut self.s, "'"));
|
|
||||||
try!(self.print_ident(*ident));
|
try!(self.print_ident(*ident));
|
||||||
try!(space(&mut self.s));
|
try!(space(&mut self.s));
|
||||||
}
|
}
|
||||||
|
@ -1513,7 +1510,6 @@ impl<'a> State<'a> {
|
||||||
try!(word(&mut self.s, "continue"));
|
try!(word(&mut self.s, "continue"));
|
||||||
try!(space(&mut self.s));
|
try!(space(&mut self.s));
|
||||||
for ident in opt_ident.iter() {
|
for ident in opt_ident.iter() {
|
||||||
try!(word(&mut self.s, "'"));
|
|
||||||
try!(self.print_ident(*ident));
|
try!(self.print_ident(*ident));
|
||||||
try!(space(&mut self.s))
|
try!(space(&mut self.s))
|
||||||
}
|
}
|
||||||
|
@ -1943,7 +1939,7 @@ impl<'a> State<'a> {
|
||||||
match *region {
|
match *region {
|
||||||
Some(ref lt) => {
|
Some(ref lt) => {
|
||||||
let token = token::get_name(lt.name);
|
let token = token::get_name(lt.name);
|
||||||
if token.get() != "static" {
|
if token.get() != "'static" {
|
||||||
try!(self.nbsp());
|
try!(self.nbsp());
|
||||||
first = false;
|
first = false;
|
||||||
try!(self.print_lifetime(lt));
|
try!(self.print_lifetime(lt));
|
||||||
|
@ -1988,7 +1984,6 @@ impl<'a> State<'a> {
|
||||||
|
|
||||||
pub fn print_lifetime(&mut self,
|
pub fn print_lifetime(&mut self,
|
||||||
lifetime: &ast::Lifetime) -> IoResult<()> {
|
lifetime: &ast::Lifetime) -> IoResult<()> {
|
||||||
try!(word(&mut self.s, "'"));
|
|
||||||
self.print_name(lifetime.name)
|
self.print_name(lifetime.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,5 +15,5 @@ macro_rules! foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
'x: loop { foo!() } //~ ERROR use of undeclared label `x`
|
'x: loop { foo!() } //~ ERROR use of undeclared label `'x`
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,5 @@ macro_rules! foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
foo!(break 'x); //~ ERROR use of undeclared label `x`
|
foo!(break 'x); //~ ERROR use of undeclared label `'x`
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,6 @@ macro_rules! foo {
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
'x: for _ in range(0,1) {
|
'x: for _ in range(0,1) {
|
||||||
foo!() //~ ERROR use of undeclared label `x`
|
foo!() //~ ERROR use of undeclared label `'x`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,5 @@ macro_rules! foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
foo!(break 'x); //~ ERROR use of undeclared label `x`
|
foo!(break 'x); //~ ERROR use of undeclared label `'x`
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
struct Foo<'static> { //~ ERROR illegal lifetime parameter name: `static`
|
struct Foo<'static> { //~ ERROR illegal lifetime parameter name: `'static`
|
||||||
x: &'static int
|
x: &'static int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
src/test/run-pass/loop-label-shadowing.rs
Normal file
19
src/test/run-pass/loop-label-shadowing.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Issue #12512.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut foo = Vec::new();
|
||||||
|
'foo: for i in [1, 2, 3].iter() {
|
||||||
|
foo.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue