Skip to content

Commit 9f899a6

Browse files
committed
error during parsing for malformed inclusive range
Now it is impossible for `...` or `a...` to reach HIR lowering without a rogue syntax extension in play.
1 parent 9799cac commit 9f899a6

File tree

2 files changed

+41
-30
lines changed

2 files changed

+41
-30
lines changed

src/libsyntax/parse/parser.rs

+38-29
Original file line numberDiff line numberDiff line change
@@ -2072,8 +2072,15 @@ impl<'a> Parser<'a> {
20722072
start: Option<P<Expr>>,
20732073
end: Option<P<Expr>>,
20742074
limits: RangeLimits)
2075-
-> ast::ExprKind {
2076-
ExprKind::Range(start, end, limits)
2075+
-> PResult<'a, ast::ExprKind> {
2076+
if end.is_none() && limits == RangeLimits::Closed {
2077+
Err(self.span_fatal_help(self.span,
2078+
"inclusive range with no end",
2079+
"currently, inclusive ranges must be bounded at the end \
2080+
(`...b` or `a...b`) -- see tracking issue #28237"))
2081+
} else {
2082+
Ok(ExprKind::Range(start, end, limits))
2083+
}
20772084
}
20782085

20792086
pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent) -> ast::ExprKind {
@@ -2961,12 +2968,12 @@ impl<'a> Parser<'a> {
29612968
lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
29622969
ExprKind::Type(lhs, rhs), None);
29632970
continue
2964-
} else if op == AssocOp::DotDot {
2965-
// If we didn’t have to handle `x..`, it would be pretty easy to generalise
2966-
// it to the Fixity::None code.
2971+
} else if op == AssocOp::DotDot || op == AssocOp::DotDotDot {
2972+
// If we didn’t have to handle `x..`/`x...`, it would be pretty easy to
2973+
// generalise it to the Fixity::None code.
29672974
//
2968-
// We have 2 alternatives here: `x..y` and `x..` The other two variants are
2969-
// handled with `parse_prefix_range_expr` call above.
2975+
// We have 2 alternatives here: `x..y`/`x...y` and `x..`/`x...` The other
2976+
// two variants are handled with `parse_prefix_range_expr` call above.
29702977
let rhs = if self.is_at_start_of_range_notation_rhs() {
29712978
let rhs = self.parse_assoc_expr_with(op.precedence() + 1,
29722979
LhsExpr::NotYetParsed);
@@ -2985,7 +2992,13 @@ impl<'a> Parser<'a> {
29852992
} else {
29862993
cur_op_span
29872994
});
2988-
let r = self.mk_range(Some(lhs), rhs, RangeLimits::HalfOpen);
2995+
let limits = if op == AssocOp::DotDot {
2996+
RangeLimits::HalfOpen
2997+
} else {
2998+
RangeLimits::Closed
2999+
};
3000+
3001+
let r = try!(self.mk_range(Some(lhs), rhs, limits));
29893002
lhs = self.mk_expr(lhs_span.lo, rhs_span.hi, r, None);
29903003
break
29913004
}
@@ -3003,8 +3016,7 @@ impl<'a> Parser<'a> {
30033016
this.parse_assoc_expr_with(op.precedence() + 1,
30043017
LhsExpr::NotYetParsed)
30053018
}),
3006-
// the only operator handled here is `...` (the other non-associative operators are
3007-
// special-cased above)
3019+
// no operators are currently handled here
30083020
Fixity::None => self.with_res(
30093021
restrictions - Restrictions::RESTRICTION_STMT_EXPR,
30103022
|this| {
@@ -3045,13 +3057,8 @@ impl<'a> Parser<'a> {
30453057
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
30463058
self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
30473059
}
3048-
AssocOp::DotDotDot => {
3049-
let (lhs_span, rhs_span) = (lhs.span, rhs.span);
3050-
let r = self.mk_range(Some(lhs), Some(rhs), RangeLimits::Closed);
3051-
self.mk_expr(lhs_span.lo, rhs_span.hi, r, None)
3052-
}
3053-
AssocOp::As | AssocOp::Colon | AssocOp::DotDot => {
3054-
self.bug("As, Colon or DotDot branch reached")
3060+
AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotDot => {
3061+
self.bug("As, Colon, DotDot or DotDotDot branch reached")
30553062
}
30563063
};
30573064

@@ -3095,21 +3102,23 @@ impl<'a> Parser<'a> {
30953102
// RHS must be parsed with more associativity than the dots.
30963103
let next_prec = AssocOp::from_token(&tok).unwrap().precedence() + 1;
30973104
Some(self.parse_assoc_expr_with(next_prec,
3098-
LhsExpr::NotYetParsed)
3099-
.map(|x|{
3100-
hi = x.span.hi;
3101-
x
3102-
})?)
3105+
LhsExpr::NotYetParsed)
3106+
.map(|x|{
3107+
hi = x.span.hi;
3108+
x
3109+
})?)
31033110
} else {
31043111
None
31053112
};
3106-
let r = self.mk_range(None,
3107-
opt_end,
3108-
if tok == token::DotDot {
3109-
RangeLimits::HalfOpen
3110-
} else {
3111-
RangeLimits::Closed
3112-
});
3113+
let limits = if tok == token::DotDot {
3114+
RangeLimits::HalfOpen
3115+
} else {
3116+
RangeLimits::Closed
3117+
};
3118+
3119+
let r = try!(self.mk_range(None,
3120+
opt_end,
3121+
limits));
31133122
Ok(self.mk_expr(lo, hi, r, attrs))
31143123
}
31153124

src/test/compile-fail/impossible_range.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ pub fn main() {
1919
0..1;
2020

2121
...; //~ERROR inclusive range with no end
22-
0...; //~ERROR unexpected token
22+
//~^HELP 28237
23+
0...; //~ERROR inclusive range with no end
24+
//~^HELP 28237
2325
...1;
2426
0...1;
2527
}

0 commit comments

Comments
 (0)