stabilize or_patterns

This commit is contained in:
mark 2020-11-21 15:12:05 -06:00
parent f5f33ec0e0
commit db5629adcb
36 changed files with 59 additions and 97 deletions

View File

@ -34,7 +34,7 @@
#![no_std]
#![forbid(unsafe_code)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#[macro_use]
extern crate alloc;

View File

@ -16,7 +16,7 @@
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
#[macro_use]

View File

@ -31,7 +31,7 @@
//! in the HIR, especially for multiple identifiers.
#![feature(crate_visibility_modifier)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(box_patterns)]
#![recursion_limit = "256"]

View File

@ -686,7 +686,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
"to use an async block, remove the `||`: `async {`"
);
gate_all!(generators, "yield syntax is experimental");
gate_all!(or_patterns, "or-patterns syntax is experimental");
gate_all!(raw_ref_op, "raw address of syntax is experimental");
gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental");
gate_all!(const_trait_impl, "const trait impls are experimental");

View File

@ -1,6 +1,6 @@
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(box_patterns)]
#![recursion_limit = "256"]

View File

@ -4,7 +4,7 @@
//! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax`
//! to this crate.
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#[macro_use]
extern crate rustc_macros;

View File

@ -8,7 +8,7 @@
#![feature(crate_visibility_modifier)]
#![feature(decl_macro)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(proc_macro_internals)]
#![feature(proc_macro_quote)]
#![recursion_limit = "256"]

View File

@ -11,7 +11,7 @@
#![feature(extern_types)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
use back::write::{create_informational_target_machine, create_target_machine};

View File

@ -6,7 +6,7 @@
#![feature(try_blocks)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(associated_type_bounds)]
#![recursion_limit = "256"]
#![feature(box_syntax)]

View File

@ -22,7 +22,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, PResult};
use rustc_feature::Features;
use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, GateOr, Parser, RecoverComma};
use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, Parser, RecoverComma};
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
use rustc_session::lint::BuiltinLintDiagnostics;
@ -917,7 +917,7 @@ pub fn parse_ast_fragment<'a>(
}
AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
AstFragmentKind::Pat => {
AstFragment::Pat(this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)?)
AstFragment::Pat(this.parse_pat_allow_top_alt(None, RecoverComma::No)?)
}
AstFragmentKind::Arms
| AstFragmentKind::Fields

View File

@ -2,7 +2,7 @@
#![feature(crate_visibility_modifier)]
#![feature(decl_macro)]
#![feature(destructuring_assignment)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_internals)]
#![feature(proc_macro_span)]

View File

@ -277,6 +277,8 @@ declare_features! (
(accepted, min_const_generics, "1.51.0", Some(74878), None),
/// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
(accepted, unsafe_block_in_unsafe_fn, "1.51.0", Some(71668), None),
/// Allows the use of or-patterns (e.g., `0 | 1`).
(accepted, or_patterns, "1.53.0", Some(54883), None),
// -------------------------------------------------------------------------
// feature-group-end: accepted features

View File

@ -488,9 +488,6 @@ 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),
/// Allows the definition of `const extern fn` and `const unsafe extern fn`.
(active, const_extern_fn, "1.40.0", Some(64926), None),

View File

@ -8,7 +8,7 @@
#![feature(extended_key_value_attributes)]
#![feature(in_band_lifetimes)]
#![feature(once_cell)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
#[macro_use]

View File

@ -1,4 +1,4 @@
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
use rustc_ast as ast;

View File

@ -20,7 +20,7 @@
#![feature(const_panic)]
#![feature(extend_one)]
#![feature(never_type)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(in_band_lifetimes)]
#![feature(control_flow_enum)]
#![recursion_limit = "512"] // For rustdoc

View File

@ -35,7 +35,7 @@
#![feature(iter_order_by)]
#![feature(never_type)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
#![feature(control_flow_enum)]

View File

@ -5,7 +5,7 @@
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(once_cell)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(proc_macro_internals)]
#![feature(min_specialization)]
#![feature(stmt_expr_attributes)]

View File

@ -39,7 +39,7 @@
#![feature(extern_types)]
#![feature(nll)]
#![feature(once_cell)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(min_specialization)]
#![feature(trusted_len)]
#![feature(test)]

View File

@ -27,7 +27,7 @@ Rust MIR: a lowered representation of Rust.
#![feature(stmt_expr_attributes)]
#![feature(trait_alias)]
#![feature(option_get_or_insert_default)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(once_cell)]
#![feature(control_flow_enum)]
#![recursion_limit = "256"]

View File

@ -10,7 +10,7 @@
#![feature(crate_visibility_modifier)]
#![feature(bool_to_option)]
#![feature(once_cell)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
#[macro_use]

View File

@ -3,7 +3,7 @@
#![feature(crate_visibility_modifier)]
#![feature(bindings_after_at)]
#![feature(iter_order_by)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(box_syntax)]
#![feature(box_patterns)]
#![recursion_limit = "256"]

View File

@ -1,4 +1,4 @@
use super::pat::{GateOr, RecoverComma, PARAM_EXPECTED};
use super::pat::{RecoverComma, PARAM_EXPECTED};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{AttrWrapper, BlockMode, ForceCollect, Parser, PathStyle, Restrictions, TokenType};
use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken};
@ -1803,7 +1803,7 @@ impl<'a> Parser<'a> {
/// The `let` token has already been eaten.
fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
let pat = self.parse_pat_allow_top_alt(None, GateOr::No, RecoverComma::Yes)?;
let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes)?;
self.expect(&token::Eq)?;
let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
@ -1866,7 +1866,7 @@ impl<'a> Parser<'a> {
_ => None,
};
let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::Yes)?;
let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes)?;
if !self.eat_keyword(kw::In) {
self.error_missing_in_for_loop();
}
@ -2073,7 +2073,7 @@ impl<'a> Parser<'a> {
let attrs = self.parse_outer_attributes()?;
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
let lo = this.token.span;
let pat = this.parse_pat_allow_top_alt(None, GateOr::No, RecoverComma::Yes)?;
let pat = this.parse_pat_allow_top_alt(None, RecoverComma::Yes)?;
let guard = if this.eat_keyword(kw::If) {
let if_span = this.prev_token.span;
let cond = this.parse_expr()?;

View File

@ -14,7 +14,7 @@ use crate::lexer::UnmatchedBrace;
pub use attr_wrapper::AttrWrapper;
pub use diagnostics::AttemptLocalParseRecovery;
use diagnostics::Error;
pub use pat::{GateOr, RecoverComma};
pub use pat::RecoverComma;
pub use path::PathStyle;
use rustc_ast::ptr::P;

View File

@ -4,7 +4,7 @@ use rustc_ast_pretty::pprust;
use rustc_errors::PResult;
use rustc_span::symbol::{kw, Ident};
use crate::parser::pat::{GateOr, RecoverComma};
use crate::parser::pat::RecoverComma;
use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle};
impl<'a> Parser<'a> {
@ -122,7 +122,7 @@ impl<'a> Parser<'a> {
token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
NonterminalKind::Pat2018 { .. } => this.parse_pat_no_top_alt(None),
NonterminalKind::Pat2021 { .. } => {
this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
this.parse_pat_allow_top_alt(None, RecoverComma::No)
}
_ => unreachable!(),
})?)

View File

@ -17,13 +17,6 @@ pub(super) const PARAM_EXPECTED: Expected = Some("parameter name");
const WHILE_PARSING_OR_MSG: &str = "while parsing this or-pattern starting here";
/// Whether or not an or-pattern should be gated when occurring in the current context.
#[derive(PartialEq, Clone, Copy)]
pub enum GateOr {
Yes,
No,
}
/// Whether or not to recover a `,` when parsing or-patterns.
#[derive(PartialEq, Copy, Clone)]
pub enum RecoverComma {
@ -64,10 +57,9 @@ impl<'a> Parser<'a> {
pub fn parse_pat_allow_top_alt(
&mut self,
expected: Expected,
gate_or: GateOr,
rc: RecoverComma,
) -> PResult<'a, P<Pat>> {
self.parse_pat_allow_top_alt_inner(expected, gate_or, rc).map(|(pat, _)| pat)
self.parse_pat_allow_top_alt_inner(expected, rc).map(|(pat, _)| pat)
}
/// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
@ -75,7 +67,6 @@ impl<'a> Parser<'a> {
fn parse_pat_allow_top_alt_inner(
&mut self,
expected: Expected,
gate_or: GateOr,
rc: RecoverComma,
) -> PResult<'a, (P<Pat>, bool)> {
// Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
@ -90,7 +81,7 @@ impl<'a> Parser<'a> {
// Parse the first pattern (`p_0`).
let first_pat = self.parse_pat_no_top_alt(expected)?;
self.maybe_recover_unexpected_comma(first_pat.span, rc, gate_or)?;
self.maybe_recover_unexpected_comma(first_pat.span, rc)?;
// If the next token is not a `|`,
// this is not an or-pattern and we should exit here.
@ -99,10 +90,6 @@ impl<'a> Parser<'a> {
// then we should really gate the leading `|`.
// This complicated procedure is done purely for diagnostics UX.
if let Some(leading_vert_span) = leading_vert_span {
if gate_or == GateOr::Yes && self.sess.gated_spans.is_ungated(sym::or_patterns) {
self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span);
}
// If there was a leading vert, treat this as an or-pattern. This improves
// diagnostics.
let span = leading_vert_span.to(self.prev_token.span);
@ -128,16 +115,11 @@ impl<'a> Parser<'a> {
err.span_label(lo, WHILE_PARSING_OR_MSG);
err
})?;
self.maybe_recover_unexpected_comma(pat.span, rc, gate_or)?;
self.maybe_recover_unexpected_comma(pat.span, rc)?;
pats.push(pat);
}
let or_pattern_span = lo.to(self.prev_token.span);
// Feature gate the or-pattern if instructed:
if gate_or == GateOr::Yes {
self.sess.gated_spans.gate(sym::or_patterns, or_pattern_span);
}
Ok((self.mk_pat(or_pattern_span, PatKind::Or(pats)), trailing_vert))
}
@ -152,14 +134,13 @@ impl<'a> Parser<'a> {
pub(super) fn parse_pat_before_ty(
&mut self,
expected: Expected,
gate_or: GateOr,
rc: RecoverComma,
syntax_loc: &str,
) -> PResult<'a, (P<Pat>, bool)> {
// We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level
// or-patterns so that we can detect when a user tries to use it. This allows us to print a
// better error message.
let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(expected, gate_or, rc)?;
let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(expected, rc)?;
let colon = self.eat(&token::Colon);
if let PatKind::Or(pats) = &pat.kind {
@ -213,12 +194,7 @@ impl<'a> Parser<'a> {
self.bump();
}
self.parse_pat_before_ty(
PARAM_EXPECTED,
GateOr::No,
RecoverComma::No,
"function parameters",
)
self.parse_pat_before_ty(PARAM_EXPECTED, RecoverComma::No, "function parameters")
}
/// Eat the or-pattern `|` separator.
@ -287,12 +263,7 @@ impl<'a> Parser<'a> {
/// Some special error handling for the "top-level" patterns in a match arm,
/// `for` loop, `let`, &c. (in contrast to subpatterns within such).
fn maybe_recover_unexpected_comma(
&mut self,
lo: Span,
rc: RecoverComma,
gate_or: GateOr,
) -> PResult<'a, ()> {
fn maybe_recover_unexpected_comma(&mut self, lo: Span, rc: RecoverComma) -> PResult<'a, ()> {
if rc == RecoverComma::No || self.token != token::Comma {
return Ok(());
}
@ -313,22 +284,18 @@ impl<'a> Parser<'a> {
if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
const MSG: &str = "try adding parentheses to match on a tuple...";
let or_suggestion =
gate_or == GateOr::No || !self.sess.gated_spans.is_ungated(sym::or_patterns);
err.span_suggestion(
seq_span,
if or_suggestion { MSG } else { MSG.trim_end_matches('.') },
MSG,
format!("({})", seq_snippet),
Applicability::MachineApplicable,
);
if or_suggestion {
err.span_suggestion(
seq_span,
"...or a vertical bar to match on multiple alternatives",
seq_snippet.replace(",", " |"),
Applicability::MachineApplicable,
);
}
err.span_suggestion(
seq_span,
"...or a vertical bar to match on multiple alternatives",
seq_snippet.replace(",", " |"),
Applicability::MachineApplicable,
);
}
Err(err)
}
@ -383,7 +350,7 @@ impl<'a> Parser<'a> {
} else if self.check(&token::OpenDelim(token::Bracket)) {
// Parse `[pat, pat,...]` as a slice pattern.
let (pats, _) = self.parse_delim_comma_seq(token::Bracket, |p| {
p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
p.parse_pat_allow_top_alt(None, RecoverComma::No)
})?;
PatKind::Slice(pats)
} else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) {
@ -596,9 +563,8 @@ 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_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
})?;
let (fields, trailing_comma) =
self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?;
// Here, `(pat,)` is a tuple pattern.
// For backward compatibility, `(..)` is a tuple pattern as well.
@ -911,9 +877,8 @@ impl<'a> Parser<'a> {
if qself.is_some() {
return self.error_qpath_before_pat(&path, "(");
}
let (fields, _) = self.parse_paren_comma_seq(|p| {
p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
})?;
let (fields, _) =
self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?;
Ok(PatKind::TupleStruct(path, fields))
}
@ -1079,7 +1044,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_allow_top_alt(None, GateOr::Yes, RecoverComma::No)?;
let pat = self.parse_pat_allow_top_alt(None, RecoverComma::No)?;
hi = pat.span;
(pat, fieldname, false)
} else {

View File

@ -1,7 +1,7 @@
use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN;
use super::diagnostics::{AttemptLocalParseRecovery, Error};
use super::expr::LhsExpr;
use super::pat::{GateOr, RecoverComma};
use super::pat::RecoverComma;
use super::path::PathStyle;
use super::TrailingToken;
use super::{AttrWrapper, BlockMode, ForceCollect, Parser, Restrictions, SemiColonMode};
@ -221,8 +221,7 @@ impl<'a> Parser<'a> {
/// Parses a local variable declaration.
fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
let lo = self.prev_token.span;
let (pat, colon) =
self.parse_pat_before_ty(None, GateOr::Yes, RecoverComma::Yes, "`let` bindings")?;
let (pat, colon) = self.parse_pat_before_ty(None, RecoverComma::Yes, "`let` bindings")?;
let (err, ty) = if colon {
// Save the state of the parser before parsing type normally, in case there is a `:`

View File

@ -10,7 +10,7 @@
test(attr(deny(warnings)))
)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(bool_to_option)]
pub use Alignment::*;

View File

@ -10,7 +10,7 @@
#![feature(crate_visibility_modifier)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
#[macro_use]

View File

@ -1,7 +1,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(control_flow_enum)]
#![feature(try_blocks)]
#![feature(associated_type_defaults)]

View File

@ -15,7 +15,7 @@
#![feature(crate_visibility_modifier)]
#![feature(format_args_capture)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
pub use rustc_hir::def::{Namespace, PerNS};

View File

@ -1,6 +1,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
mod dump_visitor;

View File

@ -1,6 +1,6 @@
#![feature(crate_visibility_modifier)]
#![feature(once_cell)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
#[macro_use]

View File

@ -90,7 +90,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(never_type)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(in_band_lifetimes)]
#![recursion_limit = "256"]

View File

@ -17,7 +17,7 @@
#![feature(in_band_lifetimes)]
#![feature(never_type)]
#![feature(crate_visibility_modifier)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(control_flow_enum)]
#![recursion_limit = "512"] // For rustdoc

View File

@ -64,7 +64,7 @@ This API is completely unstable and subject to change.
#![feature(in_band_lifetimes)]
#![feature(is_sorted)]
#![feature(nll)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(try_blocks)]
#![feature(never_type)]
#![feature(slice_partition_dedup)]