Skip to content

Commit be23d44

Browse files
committed
Auto merge of rust-lang#27065 - marcusklaas:loop-label, r=nrc
This closes rust-lang#27042. I'd love to know if there's a way to make a regression test for this!
2 parents 5d30413 + 1296360 commit be23d44

File tree

2 files changed

+49
-19
lines changed

2 files changed

+49
-19
lines changed

src/libsyntax/parse/parser.rs

+23-19
Original file line numberDiff line numberDiff line change
@@ -2099,28 +2099,32 @@ impl<'a> Parser<'a> {
20992099
return self.parse_if_expr();
21002100
}
21012101
if try!(self.eat_keyword(keywords::For) ){
2102-
return self.parse_for_expr(None);
2102+
let lo = self.last_span.lo;
2103+
return self.parse_for_expr(None, lo);
21032104
}
21042105
if try!(self.eat_keyword(keywords::While) ){
2105-
return self.parse_while_expr(None);
2106+
let lo = self.last_span.lo;
2107+
return self.parse_while_expr(None, lo);
21062108
}
21072109
if self.token.is_lifetime() {
21082110
let lifetime = self.get_lifetime();
2111+
let lo = self.span.lo;
21092112
try!(self.bump());
21102113
try!(self.expect(&token::Colon));
21112114
if try!(self.eat_keyword(keywords::While) ){
2112-
return self.parse_while_expr(Some(lifetime))
2115+
return self.parse_while_expr(Some(lifetime), lo)
21132116
}
21142117
if try!(self.eat_keyword(keywords::For) ){
2115-
return self.parse_for_expr(Some(lifetime))
2118+
return self.parse_for_expr(Some(lifetime), lo)
21162119
}
21172120
if try!(self.eat_keyword(keywords::Loop) ){
2118-
return self.parse_loop_expr(Some(lifetime))
2121+
return self.parse_loop_expr(Some(lifetime), lo)
21192122
}
21202123
return Err(self.fatal("expected `while`, `for`, or `loop` after a label"))
21212124
}
21222125
if try!(self.eat_keyword(keywords::Loop) ){
2123-
return self.parse_loop_expr(None);
2126+
let lo = self.last_span.lo;
2127+
return self.parse_loop_expr(None, lo);
21242128
}
21252129
if try!(self.eat_keyword(keywords::Continue) ){
21262130
let lo = self.span.lo;
@@ -2892,48 +2896,48 @@ impl<'a> Parser<'a> {
28922896
}
28932897

28942898
/// Parse a 'for' .. 'in' expression ('for' token already eaten)
2895-
pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> {
2899+
pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>,
2900+
span_lo: BytePos) -> PResult<P<Expr>> {
28962901
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
28972902

2898-
let lo = self.last_span.lo;
28992903
let pat = try!(self.parse_pat_nopanic());
29002904
try!(self.expect_keyword(keywords::In));
29012905
let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
29022906
let loop_block = try!(self.parse_block());
29032907
let hi = self.last_span.hi;
29042908

2905-
Ok(self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident)))
2909+
Ok(self.mk_expr(span_lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident)))
29062910
}
29072911

29082912
/// Parse a 'while' or 'while let' expression ('while' token already eaten)
2909-
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> {
2913+
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>,
2914+
span_lo: BytePos) -> PResult<P<Expr>> {
29102915
if self.token.is_keyword(keywords::Let) {
2911-
return self.parse_while_let_expr(opt_ident);
2916+
return self.parse_while_let_expr(opt_ident, span_lo);
29122917
}
2913-
let lo = self.last_span.lo;
29142918
let cond = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
29152919
let body = try!(self.parse_block());
29162920
let hi = body.span.hi;
2917-
return Ok(self.mk_expr(lo, hi, ExprWhile(cond, body, opt_ident)));
2921+
return Ok(self.mk_expr(span_lo, hi, ExprWhile(cond, body, opt_ident)));
29182922
}
29192923

29202924
/// Parse a 'while let' expression ('while' token already eaten)
2921-
pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> {
2922-
let lo = self.last_span.lo;
2925+
pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>,
2926+
span_lo: BytePos) -> PResult<P<Expr>> {
29232927
try!(self.expect_keyword(keywords::Let));
29242928
let pat = try!(self.parse_pat_nopanic());
29252929
try!(self.expect(&token::Eq));
29262930
let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
29272931
let body = try!(self.parse_block());
29282932
let hi = body.span.hi;
2929-
return Ok(self.mk_expr(lo, hi, ExprWhileLet(pat, expr, body, opt_ident)));
2933+
return Ok(self.mk_expr(span_lo, hi, ExprWhileLet(pat, expr, body, opt_ident)));
29302934
}
29312935

2932-
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> {
2933-
let lo = self.last_span.lo;
2936+
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>,
2937+
span_lo: BytePos) -> PResult<P<Expr>> {
29342938
let body = try!(self.parse_block());
29352939
let hi = body.span.hi;
2936-
Ok(self.mk_expr(lo, hi, ExprLoop(body, opt_ident)))
2940+
Ok(self.mk_expr(span_lo, hi, ExprLoop(body, opt_ident)))
29372941
}
29382942

29392943
fn parse_match_expr(&mut self) -> PResult<P<Expr>> {

src/test/compile-fail/issue-27042.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Regression test for #27042. Test that a loop's label is included in its span.
12+
13+
fn main() {
14+
let _: i32 =
15+
'a: //~ ERROR mismatched types
16+
loop { break };
17+
let _: i32 =
18+
'b: //~ ERROR mismatched types
19+
while true { break };
20+
let _: i32 =
21+
'c: //~ ERROR mismatched types
22+
for _ in None { break };
23+
let _: i32 =
24+
'd: //~ ERROR mismatched types
25+
while let Some(_) = None { break };
26+
}

0 commit comments

Comments
 (0)