diff options
| author | Alex Burka <alex@alexburka.com> | 2017-09-19 05:40:04 +0000 |
|---|---|---|
| committer | Badel2 <2badel2@gmail.com> | 2017-09-22 22:05:18 +0200 |
| commit | e64efc91f49affb265328e354c8c8f0544daa462 (patch) | |
| tree | ab6832194ec3c23ab7033941b885f164ebc37686 /src/libsyntax | |
| parent | 3eb19bf9b160825cd338b9419551670a30962c4e (diff) | |
| download | rust-e64efc91f49affb265328e354c8c8f0544daa462.tar.gz rust-e64efc91f49affb265328e354c8c8f0544daa462.zip | |
Add support for `..=` syntax
Add ..= to the parser Add ..= to libproc_macro Add ..= to ICH Highlight ..= in rustdoc Update impl Debug for RangeInclusive to ..= Replace `...` to `..=` in range docs Make the dotdoteq warning point to the ... Add warning for ... in expressions Updated more tests to the ..= syntax Updated even more tests to the ..= syntax Updated the inclusive_range entry in unstable book
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/diagnostic_list.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/quote.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/lexer/mod.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 50 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 35 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/util/parser.rs | 17 |
8 files changed, 74 insertions, 41 deletions
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index b29883670bd..c3cf4747835 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -291,7 +291,7 @@ Erroneous code example: fn main() { let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; - let x = &tmp[1...]; // error: inclusive range was used with no end + let x = &tmp[1..=]; // error: inclusive range was used with no end } ``` @@ -312,7 +312,7 @@ Or put an end to your inclusive range: fn main() { let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; - let x = &tmp[1...3]; // ok! + let x = &tmp[1..=3]; // ok! } ``` "##, diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index c3f3a59c302..bd8c9a0ed40 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -686,7 +686,9 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> { token::At => "At", token::Dot => "Dot", token::DotDot => "DotDot", + token::DotEq => "DotEq", token::DotDotDot => "DotDotDot", + token::DotDotEq => "DotDotEq", token::Comma => "Comma", token::Semi => "Semi", token::Colon => "Colon", diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1fef382c83a..2fc451d5d00 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -261,7 +261,7 @@ declare_features! ( // rustc internal (active, abi_vectorcall, "1.7.0", None), - // a...b and ...b + // a..=b and ..=b (active, inclusive_range_syntax, "1.7.0", Some(28237)), // X..Y patterns diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index ce3f16d2ba1..1cb7b0eca58 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1131,6 +1131,9 @@ impl<'a> StringReader<'a> { if self.ch_is('.') { self.bump(); Ok(token::DotDotDot) + } else if self.ch_is('=') { + self.bump(); + Ok(token::DotDotEq) } else { Ok(token::DotDot) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a2514a04254..80c976abd19 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -432,7 +432,7 @@ impl Error { Error::InclusiveRangeWithNoEnd => { let mut err = struct_span_err!(handler, sp, E0586, "inclusive range with no end"); - err.help("inclusive ranges must be bounded at the end (`...b` or `a...b`)"); + err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)"); err } } @@ -2710,7 +2710,7 @@ impl<'a> Parser<'a> { LhsExpr::AttributesParsed(attrs) => Some(attrs), _ => None, }; - if self.token == token::DotDot || self.token == token::DotDotDot { + if [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token) { return self.parse_prefix_range_expr(attrs); } else { self.parse_prefix_expr(attrs)? @@ -2744,6 +2744,10 @@ impl<'a> Parser<'a> { if op.precedence() < min_prec { break; } + // Warn about deprecated ... syntax (until SNAP) + if self.token == token::DotDotDot { + self.warn_dotdoteq(self.span); + } self.bump(); if op.is_comparison() { self.check_no_chained_comparison(&lhs, &op); @@ -2770,12 +2774,13 @@ impl<'a> Parser<'a> { } }; continue - } else if op == AssocOp::DotDot || op == AssocOp::DotDotDot { - // If we didn’t have to handle `x..`/`x...`, it would be pretty easy to + } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { + // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to // generalise it to the Fixity::None code. // - // We have 2 alternatives here: `x..y`/`x...y` and `x..`/`x...` The other + // We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other // two variants are handled with `parse_prefix_range_expr` call above. + // (and `x...y`/`x...` until SNAP) let rhs = if self.is_at_start_of_range_notation_rhs() { Some(self.parse_assoc_expr_with(op.precedence() + 1, LhsExpr::NotYetParsed)?) @@ -2852,8 +2857,8 @@ impl<'a> Parser<'a> { let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs); self.mk_expr(span, aopexpr, ThinVec::new()) } - AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotDot => { - self.bug("As, Colon, DotDot or DotDotDot branch reached") + AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => { + self.bug("AssocOp should have been handled by special case") } }; @@ -2949,17 +2954,22 @@ impl<'a> Parser<'a> { } } - /// Parse prefix-forms of range notation: `..expr`, `..`, `...expr` + /// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr` (and `...expr` until SNAP) fn parse_prefix_range_expr(&mut self, already_parsed_attrs: Option<ThinVec<Attribute>>) -> PResult<'a, P<Expr>> { - debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot, - "parse_prefix_range_expr: token {:?} is not DotDot or DotDotDot", + // SNAP remove DotDotDot + debug_assert!([token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token), + "parse_prefix_range_expr: token {:?} is not DotDot/DotDotDot/DotDotEq", self.token); let tok = self.token.clone(); let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; let lo = self.span; let mut hi = self.span; + // Warn about deprecated ... syntax (until SNAP) + if tok == token::DotDotDot { + self.warn_dotdoteq(self.span); + } self.bump(); let opt_end = if self.is_at_start_of_range_notation_rhs() { // RHS must be parsed with more associativity than the dots. @@ -3450,7 +3460,7 @@ impl<'a> Parser<'a> { fn parse_as_ident(&mut self) -> bool { self.look_ahead(1, |t| match *t { token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) | - token::DotDotDot | token::ModSep | token::Not => Some(false), + token::DotDotDot | token::DotDotEq | token::ModSep | token::Not => Some(false), // ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the // range pattern branch token::DotDot => None, @@ -3544,11 +3554,12 @@ impl<'a> Parser<'a> { let mac = respan(lo.to(self.prev_span), Mac_ { path: path, tts: tts }); pat = PatKind::Mac(mac); } - token::DotDotDot | token::DotDot => { + token::DotDotDot | token::DotDotEq | token::DotDot => { let end_kind = match self.token { token::DotDot => RangeEnd::Excluded, - token::DotDotDot => RangeEnd::Included, - _ => panic!("can only parse `..` or `...` for ranges (checked above)"), + token::DotDotDot | token::DotDotEq => RangeEnd::Included, + _ => panic!("can only parse `..`/`...`/`..=` for ranges \ + (checked above)"), }; // Parse range let span = lo.to(self.prev_span); @@ -3590,6 +3601,9 @@ impl<'a> Parser<'a> { if self.eat(&token::DotDotDot) { let end = self.parse_pat_range_end()?; pat = PatKind::Range(begin, end, RangeEnd::Included); + } else if self.eat(&token::DotDotEq) { + let end = self.parse_pat_range_end()?; + pat = PatKind::Range(begin, end, RangeEnd::Included); } else if self.eat(&token::DotDot) { let end = self.parse_pat_range_end()?; pat = PatKind::Range(begin, end, RangeEnd::Excluded); @@ -3973,7 +3987,7 @@ impl<'a> Parser<'a> { token::BinOp(token::Minus) | token::BinOp(token::Star) | token::BinOp(token::And) | token::BinOp(token::Or) | token::AndAnd | token::OrOr | - token::DotDot | token::DotDotDot => false, + token::DotDot | token::DotDotDot | token::DotDotEq => false, _ => true, } { self.warn_missing_semicolon(); @@ -4195,6 +4209,12 @@ impl<'a> Parser<'a> { }).emit(); } + fn warn_dotdoteq(&self, span: Span) { + self.diagnostic().struct_span_warn(span, { + "`...` is being replaced by `..=`" + }).emit(); + } + // Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. // BOUND = TY_BOUND | LT_BOUND // LT_BOUND = LIFETIME (e.g. `'a`) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index a316733bdb5..4888654fac9 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -152,6 +152,8 @@ pub enum Token { Dot, DotDot, DotDotDot, + DotDotEq, + DotEq, // HACK(durka42) never produced by the parser, only used for libproc_macro Comma, Semi, Colon, @@ -212,18 +214,19 @@ impl Token { pub fn can_begin_expr(&self) -> bool { match *self { Ident(ident) => ident_can_begin_expr(ident), // value name or keyword - OpenDelim(..) | // tuple, array or block - Literal(..) | // literal - Not | // operator not - BinOp(Minus) | // unary minus - BinOp(Star) | // dereference - BinOp(Or) | OrOr | // closure - BinOp(And) | // reference - AndAnd | // double reference - DotDot | DotDotDot | // range notation - Lt | BinOp(Shl) | // associated path - ModSep | // global path - Pound => true, // expression attributes + OpenDelim(..) | // tuple, array or block + Literal(..) | // literal + Not | // operator not + BinOp(Minus) | // unary minus + BinOp(Star) | // dereference + BinOp(Or) | OrOr | // closure + BinOp(And) | // reference + AndAnd | // double reference + DotDot | DotDotDot | DotDotEq | // range notation + // SNAP remove DotDotDot + Lt | BinOp(Shl) | // associated path + ModSep | // global path + Pound => true, // expression attributes Interpolated(ref nt) => match nt.0 { NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true, _ => false, @@ -402,10 +405,12 @@ impl Token { Dot => match joint { Dot => DotDot, DotDot => DotDotDot, + DotEq => DotDotEq, _ => return None, }, DotDot => match joint { Dot => DotDotDot, + Eq => DotDotEq, _ => return None, }, Colon => match joint { @@ -413,9 +418,9 @@ impl Token { _ => return None, }, - Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | Comma | - Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | - OpenDelim(..) | CloseDelim(..) | Underscore => return None, + Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq | + DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | + Question | OpenDelim(..) | CloseDelim(..) | Underscore => return None, Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) | Whitespace | Comment | Shebang(..) | Eof => return None, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9903dc50f36..cc4b34854fc 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -203,6 +203,8 @@ pub fn token_to_string(tok: &Token) -> String { token::Dot => ".".to_string(), token::DotDot => "..".to_string(), token::DotDotDot => "...".to_string(), + token::DotDotEq => "..=".to_string(), + token::DotEq => ".=".to_string(), token::Comma => ",".to_string(), token::Semi => ";".to_string(), token::Colon => ":".to_string(), diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index a4f06cb1b45..590874806d7 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -62,8 +62,8 @@ pub enum AssocOp { As, /// `..` range DotDot, - /// `...` range - DotDotDot, + /// `..=` range + DotDotEq, /// `:` Colon, } @@ -105,7 +105,8 @@ impl AssocOp { Token::AndAnd => Some(LAnd), Token::OrOr => Some(LOr), Token::DotDot => Some(DotDot), - Token::DotDotDot => Some(DotDotDot), + Token::DotDotEq => Some(DotDotEq), + Token::DotDotDot => Some(DotDotEq), // remove this after SNAP Token::Colon => Some(Colon), _ if t.is_keyword(keywords::As) => Some(As), _ => None @@ -151,7 +152,7 @@ impl AssocOp { Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7, LAnd => 6, LOr => 5, - DotDot | DotDotDot => 4, + DotDot | DotDotEq => 4, Inplace => 3, Assign | AssignOp(_) => 2, } @@ -166,7 +167,7 @@ impl AssocOp { As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | LAnd | LOr | Colon => Fixity::Left, - DotDot | DotDotDot => Fixity::None + DotDot | DotDotEq => Fixity::None } } @@ -176,7 +177,7 @@ impl AssocOp { Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true, Inplace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | - DotDot | DotDotDot | Colon => false + DotDot | DotDotEq | Colon => false } } @@ -186,7 +187,7 @@ impl AssocOp { Assign | AssignOp(_) | Inplace => true, Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | - LOr | DotDot | DotDotDot | Colon => false + LOr | DotDot | DotDotEq | Colon => false } } @@ -211,7 +212,7 @@ impl AssocOp { BitOr => Some(BinOpKind::BitOr), LAnd => Some(BinOpKind::And), LOr => Some(BinOpKind::Or), - Inplace | Assign | AssignOp(_) | As | DotDot | DotDotDot | Colon => None + Inplace | Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None } } } |
