diff options
| author | Artyom Pavlov <newpavlov@gmail.com> | 2019-08-20 10:08:57 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-20 10:08:57 +0000 |
| commit | e500fc3171a899f713a269ccee6f480b9db4859b (patch) | |
| tree | 8aa95c5dd723ddc09ffbe724c44cb701f8bde7e5 /src/libsyntax | |
| parent | 34c9f8c6490bb1179c504bccd51b2827c05f10db (diff) | |
| parent | 7858dc237d70fc0c5a31eb528dfab1ad0baf6a27 (diff) | |
Merge branch 'master' into redox_builder
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/base.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 25 | ||||
| -rw-r--r-- | src/libsyntax/ext/placeholders.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/mut_visit.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/parse/lexer/mod.rs | 81 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser/pat.rs | 41 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 36 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 7 |
11 files changed, 116 insertions, 113 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9091607629e..50e428ea0cc 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -572,9 +572,10 @@ impl Pat { match &self.node { PatKind::Ident(_, _, Some(p)) => p.walk(it), PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk(it)), - PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) => { - s.iter().all(|p| p.walk(it)) - } + PatKind::TupleStruct(_, s) + | PatKind::Tuple(s) + | PatKind::Slice(s) + | PatKind::Or(s) => s.iter().all(|p| p.walk(it)), PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it), PatKind::Wild | PatKind::Rest @@ -648,6 +649,10 @@ pub enum PatKind { /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). TupleStruct(Path, Vec<P<Pat>>), + /// An or-pattern `A | B | C`. + /// Invariant: `pats.len() >= 2`. + Or(Vec<P<Pat>>), + /// A possibly qualified path pattern. /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants /// or associated constants. Qualified path patterns `<A>::B::C`/`<A as Trait>::B::C` can diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index fb1bf4d7160..b0a4a6af983 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,4 +1,4 @@ -use crate::ast::{self, Attribute, Name, PatKind}; +use crate::ast::{self, NodeId, Attribute, Name, PatKind}; use crate::attr::{HasAttrs, Stability, Deprecation}; use crate::source_map::SourceMap; use crate::edition::Edition; @@ -671,13 +671,13 @@ bitflags::bitflags! { } pub trait Resolver { - fn next_node_id(&mut self) -> ast::NodeId; + fn next_node_id(&mut self) -> NodeId; - fn get_module_scope(&mut self, id: ast::NodeId) -> ExpnId; + fn get_module_scope(&mut self, id: NodeId) -> ExpnId; fn resolve_dollar_crates(&mut self); fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, - derives: &[ExpnId]); + extra_placeholders: &[NodeId]); fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); fn resolve_imports(&mut self); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index dac402921b9..c1d52c97455 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -291,7 +291,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Unresolved macros produce dummy outputs as a recovery measure. invocations.reverse(); let mut expanded_fragments = Vec::new(); - let mut derives: FxHashMap<ExpnId, Vec<_>> = FxHashMap::default(); + let mut all_derive_placeholders: FxHashMap<ExpnId, Vec<_>> = FxHashMap::default(); let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { @@ -347,13 +347,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut item = self.fully_configure(item); item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive)); - let derives = derives.entry(invoc.expansion_data.id).or_default(); + let derive_placeholders = + all_derive_placeholders.entry(invoc.expansion_data.id).or_default(); - derives.reserve(traits.len()); + derive_placeholders.reserve(traits.len()); invocations.reserve(traits.len()); for path in traits { let expn_id = ExpnId::fresh(None); - derives.push(expn_id); + derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id)); invocations.push(Invocation { kind: InvocationKind::Derive { path, item: item.clone() }, fragment_kind: invoc.fragment_kind, @@ -365,7 +366,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } let fragment = invoc.fragment_kind .expect_from_annotatables(::std::iter::once(item)); - self.collect_invocations(fragment, derives) + self.collect_invocations(fragment, derive_placeholders) } else { unreachable!() }; @@ -384,10 +385,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Finally incorporate all the expanded macros into the input AST fragment. let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expanded_fragments) = expanded_fragments.pop() { - for (mark, expanded_fragment) in expanded_fragments.into_iter().rev() { - let derives = derives.remove(&mark).unwrap_or_else(Vec::new); - placeholder_expander.add(NodeId::placeholder_from_expn_id(mark), - expanded_fragment, derives); + for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { + let derive_placeholders = + all_derive_placeholders.remove(&expn_id).unwrap_or_else(Vec::new); + placeholder_expander.add(NodeId::placeholder_from_expn_id(expn_id), + expanded_fragment, derive_placeholders); } } fragment_with_placeholders.mut_visit_with(&mut placeholder_expander); @@ -404,7 +406,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s. /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and /// prepares data for resolving paths of macro invocations. - fn collect_invocations(&mut self, mut fragment: AstFragment, derives: &[ExpnId]) + fn collect_invocations(&mut self, mut fragment: AstFragment, extra_placeholders: &[NodeId]) -> (AstFragment, Vec<Invocation>) { // Resolve `$crate`s in the fragment for pretty-printing. self.cx.resolver.resolve_dollar_crates(); @@ -423,9 +425,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { collector.invocations }; + // FIXME: Merge `extra_placeholders` into the `fragment` as regular placeholders. if self.monotonic { self.cx.resolver.visit_ast_fragment_with_placeholders( - self.cx.current_expansion.id, &fragment, derives); + self.cx.current_expansion.id, &fragment, extra_placeholders); } (fragment, invocations) diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 2d05f8f0b00..d800cfedcfb 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -2,7 +2,6 @@ use crate::ast::{self, NodeId}; use crate::source_map::{DUMMY_SP, dummy_spanned}; use crate::ext::base::ExtCtxt; use crate::ext::expand::{AstFragment, AstFragmentKind}; -use crate::ext::hygiene::ExpnId; use crate::tokenstream::TokenStream; use crate::mut_visit::*; use crate::ptr::P; @@ -86,11 +85,11 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } } - pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, derives: Vec<ExpnId>) { + pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, placeholders: Vec<NodeId>) { fragment.mut_visit_with(self); if let AstFragment::Items(mut items) = fragment { - for derive in derives { - match self.remove(NodeId::placeholder_from_expn_id(derive)) { + for placeholder in placeholders { + match self.remove(placeholder) { AstFragment::Items(derived_items) => items.extend(derived_items), _ => unreachable!(), } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1a87a903156..bbc3ae28225 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -559,6 +559,9 @@ declare_features! ( // Allows `impl Trait` to be used inside type aliases (RFC 2515). (active, type_alias_impl_trait, "1.38.0", Some(63063), None), + // Allows the use of or-patterns, e.g. `0 | 1`. + (active, or_patterns, "1.38.0", Some(54883), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- @@ -571,6 +574,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::impl_trait_in_bindings, sym::generic_associated_types, sym::const_generics, + sym::or_patterns, sym::let_chains, ]; @@ -2443,6 +2447,7 @@ pub fn check_crate(krate: &ast::Crate, gate_all!(let_chains_spans, let_chains, "`let` expressions in this position are experimental"); gate_all!(async_closure_spans, async_closure, "async closures are unstable"); gate_all!(yield_spans, generators, "yield syntax is experimental"); + gate_all!(or_pattern_spans, or_patterns, "or-patterns syntax is experimental"); let visitor = &mut PostExpansionVisitor { context: &ctx, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 18d4a646355..9785f8e2de0 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1050,7 +1050,6 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) { vis.visit_span(span); }; } - PatKind::Tuple(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), PatKind::Box(inner) => vis.visit_pat(inner), PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner), PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => { @@ -1058,7 +1057,9 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) { vis.visit_expr(e2); vis.visit_span(span); } - PatKind::Slice(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), + PatKind::Tuple(elems) + | PatKind::Slice(elems) + | PatKind::Or(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), PatKind::Paren(inner) => vis.visit_pat(inner), PatKind::Mac(mac) => vis.visit_mac(mac), } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 17629d392cd..bdf468a52bb 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -8,9 +8,7 @@ use syntax_pos::{BytePos, Pos, Span}; use rustc_lexer::Base; use rustc_lexer::unescape; -use std::borrow::Cow; use std::char; -use std::iter; use std::convert::TryInto; use rustc_data_structures::sync::Lrc; use log::debug; @@ -181,18 +179,7 @@ impl<'a> StringReader<'a> { let string = self.str_from(start); // comments with only more "/"s are not doc comments let tok = if is_doc_comment(string) { - let mut idx = 0; - loop { - idx = match string[idx..].find('\r') { - None => break, - Some(it) => idx + it + 1 - }; - if string[idx..].chars().next() != Some('\n') { - self.err_span_(start + BytePos(idx as u32 - 1), - start + BytePos(idx as u32), - "bare CR not allowed in doc-comment"); - } - } + self.forbid_bare_cr(start, string, "bare CR not allowed in doc-comment"); token::DocComment(Symbol::intern(string)) } else { token::Comment @@ -217,15 +204,10 @@ impl<'a> StringReader<'a> { } let tok = if is_doc_comment { - let has_cr = string.contains('\r'); - let string = if has_cr { - self.translate_crlf(start, - string, - "bare CR not allowed in block doc-comment") - } else { - string.into() - }; - token::DocComment(Symbol::intern(&string[..])) + self.forbid_bare_cr(start, + string, + "bare CR not allowed in block doc-comment"); + token::DocComment(Symbol::intern(string)) } else { token::Comment }; @@ -516,49 +498,16 @@ impl<'a> StringReader<'a> { &self.src[self.src_index(start)..self.src_index(end)] } - /// Converts CRLF to LF in the given string, raising an error on bare CR. - fn translate_crlf<'b>(&self, start: BytePos, s: &'b str, errmsg: &'b str) -> Cow<'b, str> { - let mut chars = s.char_indices().peekable(); - while let Some((i, ch)) = chars.next() { - if ch == '\r' { - if let Some((lf_idx, '\n')) = chars.peek() { - return translate_crlf_(self, start, s, *lf_idx, chars, errmsg).into(); - } - let pos = start + BytePos(i as u32); - let end_pos = start + BytePos((i + ch.len_utf8()) as u32); - self.err_span_(pos, end_pos, errmsg); - } - } - return s.into(); - - fn translate_crlf_(rdr: &StringReader<'_>, - start: BytePos, - s: &str, - mut j: usize, - mut chars: iter::Peekable<impl Iterator<Item = (usize, char)>>, - errmsg: &str) - -> String { - let mut buf = String::with_capacity(s.len()); - // Skip first CR - buf.push_str(&s[.. j - 1]); - while let Some((i, ch)) = chars.next() { - if ch == '\r' { - if j < i { - buf.push_str(&s[j..i]); - } - let next = i + ch.len_utf8(); - j = next; - if chars.peek().map(|(_, ch)| *ch) != Some('\n') { - let pos = start + BytePos(i as u32); - let end_pos = start + BytePos(next as u32); - rdr.err_span_(pos, end_pos, errmsg); - } - } - } - if j < s.len() { - buf.push_str(&s[j..]); - } - buf + fn forbid_bare_cr(&self, start: BytePos, s: &str, errmsg: &str) { + let mut idx = 0; + loop { + idx = match s[idx..].find('\r') { + None => break, + Some(it) => idx + it + 1 + }; + self.err_span_(start + BytePos(idx as u32 - 1), + start + BytePos(idx as u32), + errmsg); } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 9088f929372..b1f3612a839 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -66,6 +66,8 @@ pub struct ParseSess { // Places where `yield e?` exprs were used and should be feature gated. pub yield_spans: Lock<Vec<Span>>, pub injected_crate_name: Once<Symbol>, + // Places where or-patterns e.g. `Some(Foo | Bar)` were used and should be feature gated. + pub or_pattern_spans: Lock<Vec<Span>>, } impl ParseSess { @@ -96,6 +98,7 @@ impl ParseSess { async_closure_spans: Lock::new(Vec::new()), yield_spans: Lock::new(Vec::new()), injected_crate_name: Once::new(), + or_pattern_spans: Lock::new(Vec::new()), } } diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index c3079d2da0c..fd458aec743 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -14,7 +14,10 @@ use errors::{Applicability, DiagnosticBuilder}; impl<'a> Parser<'a> { /// Parses a pattern. - pub fn parse_pat(&mut self, expected: Option<&'static str>) -> PResult<'a, P<Pat>> { + pub fn parse_pat( + &mut self, + expected: Option<&'static str> + ) -> PResult<'a, P<Pat>> { self.parse_pat_with_range_pat(true, expected) } @@ -97,6 +100,34 @@ impl<'a> Parser<'a> { Ok(()) } + /// Parses a pattern, that may be a or-pattern (e.g. `Some(Foo | Bar)`). + fn parse_pat_with_or(&mut self, expected: Option<&'static str>) -> PResult<'a, P<Pat>> { + // Parse the first pattern. + let first_pat = self.parse_pat(expected)?; + + // If the next token is not a `|`, this is not an or-pattern and + // we should exit here. + if !self.check(&token::BinOp(token::Or)) { + return Ok(first_pat) + } + + let lo = first_pat.span; + + let mut pats = vec![first_pat]; + + while self.eat(&token::BinOp(token::Or)) { + pats.push(self.parse_pat_with_range_pat( + true, expected + )?); + } + + let or_pattern_span = lo.to(self.prev_span); + + self.sess.or_pattern_spans.borrow_mut().push(or_pattern_span); + + Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats))) + } + /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are /// allowed). fn parse_pat_with_range_pat( @@ -240,7 +271,9 @@ impl<'a> Parser<'a> { /// Parse a tuple or parenthesis pattern. fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { - let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; + let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| { + p.parse_pat_with_or(None) + })?; // Here, `(pat,)` is a tuple pattern. // For backward compatibility, `(..)` is a tuple pattern as well. @@ -483,7 +516,7 @@ impl<'a> Parser<'a> { err.span_label(self.token.span, msg); return Err(err); } - let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; + let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or(None))?; Ok(PatKind::TupleStruct(path, fields)) } @@ -627,7 +660,7 @@ impl<'a> Parser<'a> { // Parsing a pattern of the form "fieldname: pat" let fieldname = self.parse_field_name()?; self.bump(); - let pat = self.parse_pat(None)?; + let pat = self.parse_pat_with_or(None)?; hi = pat.span; (pat, fieldname, false) } else { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 8a7009828bc..4dc00af4860 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -436,18 +436,30 @@ pub trait PrintState<'a>: std::ops::Deref<Target=pp::Printer> + std::ops::DerefM fn print_ident(&mut self, ident: ast::Ident); fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool); - fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) + fn strsep<T, F>(&mut self, sep: &'static str, space_before: bool, + b: Breaks, elts: &[T], mut op: F) where F: FnMut(&mut Self, &T), { self.rbox(0, b); - let mut first = true; - for elt in elts { - if first { first = false; } else { self.word_space(","); } - op(self, elt); + if let Some((first, rest)) = elts.split_first() { + op(self, first); + for elt in rest { + if space_before { + self.space(); + } + self.word_space(sep); + op(self, elt); + } } self.end(); } + fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], op: F) + where F: FnMut(&mut Self, &T), + { + self.strsep(",", false, b, elts, op) + } + fn maybe_print_comment(&mut self, pos: BytePos) { while let Some(ref cmnt) = self.next_comment() { if cmnt.pos < pos { @@ -2353,6 +2365,9 @@ impl<'a> State<'a> { self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); self.pclose(); } + PatKind::Or(ref pats) => { + self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(p)); + } PatKind::Path(None, ref path) => { self.print_path(path, true, 0); } @@ -2429,16 +2444,7 @@ impl<'a> State<'a> { } fn print_pats(&mut self, pats: &[P<ast::Pat>]) { - let mut first = true; - for p in pats { - if first { - first = false; - } else { - self.s.space(); - self.word_space("|"); - } - self.print_pat(p); - } + self.strsep("|", true, Inconsistent, pats, |s, p| s.print_pat(p)); } fn print_arm(&mut self, arm: &ast::Arm) { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 6648347d4ae..91b92d84a81 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -447,9 +447,6 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { visitor.visit_pat(&field.pat) } } - PatKind::Tuple(ref elems) => { - walk_list!(visitor, visit_pat, elems); - } PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) | PatKind::Paren(ref subpattern) => { @@ -465,7 +462,9 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { visitor.visit_expr(upper_bound); } PatKind::Wild | PatKind::Rest => {}, - PatKind::Slice(ref elems) => { + PatKind::Tuple(ref elems) + | PatKind::Slice(ref elems) + | PatKind::Or(ref elems) => { walk_list!(visitor, visit_pat, elems); } PatKind::Mac(ref mac) => visitor.visit_mac(mac), |
