diff options
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/diagnostic_list.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/base.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 73 | ||||
| -rw-r--r-- | src/libsyntax/ext/quote.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 30 | ||||
| -rw-r--r-- | src/libsyntax/parse/lexer/mod.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 71 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 35 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/util/parser.rs | 17 |
11 files changed, 179 insertions, 77 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 496be8b3eb2..0504e889ea1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -538,11 +538,17 @@ pub enum BindingMode { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum RangeEnd { - Included, + Included(RangeSyntax), Excluded, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum RangeSyntax { + DotDotDot, + DotDotEq, +} + +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum PatKind { /// Represents a wildcard pattern (`_`) Wild, @@ -578,7 +584,7 @@ pub enum PatKind { Ref(P<Pat>, Mutability), /// A literal Lit(P<Expr>), - /// A range pattern, e.g. `1...2` or `1..2` + /// A range pattern, e.g. `1...2`, `1..=2` or `1..2` Range(P<Expr>, P<Expr>, RangeEnd), /// `[a, b, ..i, y, z]` is represented as: /// `PatKind::Slice(box [a, b], Some(i), box [y, z])` 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/base.rs b/src/libsyntax/ext/base.rs index c139cfeaebf..0e05cce35e2 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -783,6 +783,10 @@ impl<'a> ExtCtxt<'a> { pub fn span_err(&self, sp: Span, msg: &str) { self.parse_sess.span_diagnostic.span_err(sp, msg); } + pub fn mut_span_err(&self, sp: Span, msg: &str) + -> DiagnosticBuilder<'a> { + self.parse_sess.span_diagnostic.mut_span_err(sp, msg) + } pub fn span_warn(&self, sp: Span, msg: &str) { self.parse_sess.span_diagnostic.span_warn(sp, msg); } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index de9c085cc78..6e7a8203b61 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -282,7 +282,33 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let expansion = self.expand_invoc(invoc, ext); self.collect_invocations(expansion, &[]) } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind { - let item = item + let derive_allowed = match item { + Annotatable::Item(ref item) => match item.node { + ast::ItemKind::Struct(..) | + ast::ItemKind::Enum(..) | + ast::ItemKind::Union(..) => true, + _ => false, + }, + _ => false, + }; + if !derive_allowed { + let attr = item.attrs().iter() + .find(|attr| attr.check_name("derive")) + .expect("`derive` attribute should exist"); + let span = attr.span; + let mut err = self.cx.mut_span_err(span, + "`derive` may only be applied to \ + structs, enums and unions"); + if let ast::AttrStyle::Inner = attr.style { + let trait_list = traits.iter() + .map(|t| format!("{}", t)).collect::<Vec<_>>(); + let suggestion = format!("#[derive({})]", trait_list.join(", ")); + err.span_suggestion(span, "try an outer attribute", suggestion); + } + err.emit(); + } + + let item = self.fully_configure(item) .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs }); let item_with_markers = add_derived_markers(&mut self.cx, item.span(), &traits, item.clone()); @@ -374,6 +400,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> { result } + fn fully_configure(&mut self, item: Annotatable) -> Annotatable { + let mut cfg = StripUnconfigured { + should_test: self.cx.ecfg.should_test, + sess: self.cx.parse_sess, + features: self.cx.ecfg.features, + }; + // Since the item itself has already been configured by the InvocationCollector, + // we know that fold result vector will contain exactly one element + match item { + Annotatable::Item(item) => { + Annotatable::Item(cfg.fold_item(item).pop().unwrap()) + } + Annotatable::TraitItem(item) => { + Annotatable::TraitItem(item.map(|item| cfg.fold_trait_item(item).pop().unwrap())) + } + Annotatable::ImplItem(item) => { + Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap())) + } + } + } + fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion { let result = match invoc.kind { InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext), @@ -714,15 +761,6 @@ struct InvocationCollector<'a, 'b: 'a> { monotonic: bool, } -macro_rules! fully_configure { - ($this:ident, $node:ident, $noop_fold:ident) => { - match $noop_fold($node, &mut $this.cfg).pop() { - Some(node) => node, - None => return SmallVector::new(), - } - } -} - impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion { let mark = Mark::fresh(self.cx.current_expansion.mark); @@ -748,13 +786,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { item: Annotatable, kind: ExpansionKind) -> Expansion { - if !traits.is_empty() && - (kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems) { - self.cx.span_err(traits[0].span, "`derive` can be only be applied to items"); - self.cx.trace_macros_diag(); - return kind.expect_from_annotatables(::std::iter::once(item)); - } - self.collect(kind, InvocationKind::Attr { attr: attr, traits: traits, item: item }) + self.collect(kind, InvocationKind::Attr { attr, traits, item }) } // If `item` is an attr invocation, remove and return the macro attribute. @@ -880,7 +912,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let (attr, traits, mut item) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = Annotatable::Item(fully_configure!(self, item, noop_fold_item)); + let item = Annotatable::Item(item); return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items(); } @@ -954,8 +986,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let (attr, traits, item) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = - Annotatable::TraitItem(P(fully_configure!(self, item, noop_fold_trait_item))); + let item = Annotatable::TraitItem(P(item)); return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems) .make_trait_items() } @@ -975,7 +1006,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let (attr, traits, item) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { - let item = Annotatable::ImplItem(P(fully_configure!(self, item, noop_fold_impl_item))); + let item = Annotatable::ImplItem(P(item)); return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems) .make_impl_items(); } 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 6560943a932..e92a7484f33 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -26,7 +26,7 @@ use self::AttributeType::*; use self::AttributeGate::*; use abi::Abi; -use ast::{self, NodeId, PatKind, RangeEnd}; +use ast::{self, NodeId, PatKind, RangeEnd, RangeSyntax}; use attr; use codemap::Spanned; use syntax_pos::Span; @@ -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 @@ -380,7 +380,7 @@ declare_features! ( // #[doc(masked)] (active, doc_masked, "1.21.0", None), - // allow `#[must_use]` on functions (RFC 1940) + // allow `#[must_use]` on functions and comparison operators (RFC 1940) (active, fn_must_use, "1.21.0", Some(43302)), // allow '|' at beginning of match arms (RFC 1925) @@ -389,6 +389,12 @@ declare_features! ( // Copy/Clone closures (RFC 2132) (active, clone_closures, "1.22.0", Some(44490)), (active, copy_closures, "1.22.0", Some(44490)), + + // allow `'_` placeholder lifetimes + (active, underscore_lifetimes, "1.22.0", Some(44524)), + + // allow `..=` in patterns (RFC 1192) + (active, dotdoteq_in_patterns, "1.22.0", Some(28237)), ); declare_features! ( @@ -721,6 +727,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), + ("rustc_synthetic", Whitelisted, Gated(Stability::Unstable, + "rustc_attrs", + "this attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable, "rustc_attrs", "internal rustc attributes will never be stable", @@ -1488,6 +1500,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, exclusive_range_pattern, pattern.span, "exclusive range pattern syntax is experimental"); } + PatKind::Range(_, _, RangeEnd::Included(RangeSyntax::DotDotEq)) => { + gate_feature_post!(&self, dotdoteq_in_patterns, pattern.span, + "`..=` syntax in patterns is experimental"); + } _ => {} } visit::walk_pat(self, pattern) @@ -1572,6 +1588,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } visit::walk_lifetime_def(self, lifetime_def) } + + fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) { + if lt.ident.name == "'_" { + gate_feature_post!(&self, underscore_lifetimes, lt.span, + "underscore lifetimes are unstable"); + } + visit::walk_lifetime(self, lt) + } } pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features { 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..d5ba4b54d90 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -38,7 +38,7 @@ use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause}; use ast::{BinOpKind, UnOp}; -use ast::RangeEnd; +use ast::{RangeEnd, RangeSyntax}; use {ast, attr}; use codemap::{self, CodeMap, Spanned, respan}; use syntax_pos::{self, Span, BytePos}; @@ -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 } } @@ -2632,7 +2632,7 @@ impl<'a> Parser<'a> { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (span, self.mk_unary(UnOp::Not, e)) + (lo.to(span), self.mk_unary(UnOp::Not, e)) } // Suggest `!` for bitwise negation when encountering a `~` token::Tilde => { @@ -2645,26 +2645,26 @@ impl<'a> Parser<'a> { err.span_label(span_of_tilde, "did you mean `!`?"); err.help("use `!` instead of `~` if you meant to perform bitwise negation"); err.emit(); - (span, self.mk_unary(UnOp::Not, e)) + (lo.to(span), self.mk_unary(UnOp::Not, e)) } token::BinOp(token::Minus) => { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (span, self.mk_unary(UnOp::Neg, e)) + (lo.to(span), self.mk_unary(UnOp::Neg, e)) } token::BinOp(token::Star) => { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (span, self.mk_unary(UnOp::Deref, e)) + (lo.to(span), self.mk_unary(UnOp::Deref, e)) } token::BinOp(token::And) | token::AndAnd => { self.expect_and()?; let m = self.parse_mutability(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (span, ExprKind::AddrOf(m, e)) + (lo.to(span), ExprKind::AddrOf(m, e)) } token::Ident(..) if self.token.is_keyword(keywords::In) => { self.bump(); @@ -2675,13 +2675,13 @@ impl<'a> Parser<'a> { let blk = self.parse_block()?; let span = blk.span; let blk_expr = self.mk_expr(span, ExprKind::Block(blk), ThinVec::new()); - (span, ExprKind::InPlace(place, blk_expr)) + (lo.to(span), ExprKind::InPlace(place, blk_expr)) } token::Ident(..) if self.token.is_keyword(keywords::Box) => { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (span, ExprKind::Box(e)) + (lo.to(span), ExprKind::Box(e)) } _ => return self.parse_dot_or_call_expr(Some(attrs)) }; @@ -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,13 @@ 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 => RangeEnd::Included(RangeSyntax::DotDotDot), + token::DotDotEq => RangeEnd::Included(RangeSyntax::DotDotEq), + _ => panic!("can only parse `..`/`...`/`..=` for ranges \ + (checked above)"), }; // Parse range let span = lo.to(self.prev_span); @@ -3589,7 +3601,12 @@ impl<'a> Parser<'a> { Ok(begin) => { if self.eat(&token::DotDotDot) { let end = self.parse_pat_range_end()?; - pat = PatKind::Range(begin, end, RangeEnd::Included); + pat = PatKind::Range(begin, end, + RangeEnd::Included(RangeSyntax::DotDotDot)); + } else if self.eat(&token::DotDotEq) { + let end = self.parse_pat_range_end()?; + pat = PatKind::Range(begin, end, + RangeEnd::Included(RangeSyntax::DotDotEq)); } else if self.eat(&token::DotDot) { let end = self.parse_pat_range_end()?; pat = PatKind::Range(begin, end, RangeEnd::Excluded); @@ -3973,7 +3990,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 +4212,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..959dd4ef30f 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -11,7 +11,7 @@ pub use self::AnnNode::*; use abi::{self, Abi}; -use ast::{self, BlockCheckMode, PatKind, RangeEnd}; +use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Attribute; use util::parser::{self, AssocOp, Fixity}; @@ -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(), @@ -2588,7 +2590,8 @@ impl<'a> State<'a> { self.print_expr(begin)?; self.s.space()?; match *end_kind { - RangeEnd::Included => self.s.word("...")?, + RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("...")?, + RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..=")?, RangeEnd::Excluded => self.s.word("..")?, } self.print_expr(end)?; 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 } } } |
