Auto merge of #54497 - ralexstokes:stabilize_pattern_parentheses, r=nikomatsakis
Stabilize pattern_parentheses feature Addresses #51087 . Stabilizes the previously unstable feature `pattern_parentheses` which enables the use of `()` in match patterns.
This commit is contained in:
commit
a2b27c19da
7 changed files with 197 additions and 161 deletions
|
@ -10,27 +10,27 @@
|
||||||
|
|
||||||
// The Rust abstract syntax tree.
|
// The Rust abstract syntax tree.
|
||||||
|
|
||||||
pub use self::UnsafeSource::*;
|
|
||||||
pub use self::GenericArgs::*;
|
pub use self::GenericArgs::*;
|
||||||
|
pub use self::UnsafeSource::*;
|
||||||
pub use symbol::{Ident, Symbol as Name};
|
pub use symbol::{Ident, Symbol as Name};
|
||||||
pub use util::parser::ExprPrecedence;
|
pub use util::parser::ExprPrecedence;
|
||||||
|
|
||||||
use syntax_pos::{Span, DUMMY_SP};
|
|
||||||
use source_map::{dummy_spanned, respan, Spanned};
|
|
||||||
use rustc_target::spec::abi::Abi;
|
|
||||||
use ext::hygiene::{Mark, SyntaxContext};
|
use ext::hygiene::{Mark, SyntaxContext};
|
||||||
use print::pprust;
|
use print::pprust;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
use rustc_data_structures::indexed_vec;
|
use rustc_data_structures::indexed_vec;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use symbol::{Symbol, keywords};
|
use rustc_target::spec::abi::Abi;
|
||||||
use ThinVec;
|
use source_map::{dummy_spanned, respan, Spanned};
|
||||||
|
use symbol::{keywords, Symbol};
|
||||||
|
use syntax_pos::{Span, DUMMY_SP};
|
||||||
use tokenstream::{ThinTokenStream, TokenStream};
|
use tokenstream::{ThinTokenStream, TokenStream};
|
||||||
|
use ThinVec;
|
||||||
|
|
||||||
use serialize::{self, Encoder, Decoder};
|
|
||||||
use std::fmt;
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
use serialize::{self, Decoder, Encoder};
|
||||||
|
use std::fmt;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
|
|
||||||
pub use rustc_target::abi::FloatTy;
|
pub use rustc_target::abi::FloatTy;
|
||||||
|
@ -54,7 +54,12 @@ pub struct Lifetime {
|
||||||
|
|
||||||
impl fmt::Debug for Lifetime {
|
impl fmt::Debug for Lifetime {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "lifetime({}: {})", self.id, pprust::lifetime_to_string(self))
|
write!(
|
||||||
|
f,
|
||||||
|
"lifetime({}: {})",
|
||||||
|
self.id,
|
||||||
|
pprust::lifetime_to_string(self)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +99,10 @@ impl Path {
|
||||||
// convert a span and an identifier to the corresponding
|
// convert a span and an identifier to the corresponding
|
||||||
// 1-segment path
|
// 1-segment path
|
||||||
pub fn from_ident(ident: Ident) -> Path {
|
pub fn from_ident(ident: Ident) -> Path {
|
||||||
Path { segments: vec![PathSegment::from_ident(ident)], span: ident.span }
|
Path {
|
||||||
|
segments: vec![PathSegment::from_ident(ident)],
|
||||||
|
span: ident.span,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a "crate root" segment for this path unless it already has it
|
// Make a "crate root" segment for this path unless it already has it
|
||||||
|
@ -284,7 +292,7 @@ pub enum TraitBoundModifier {
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub enum GenericBound {
|
pub enum GenericBound {
|
||||||
Trait(PolyTraitRef, TraitBoundModifier),
|
Trait(PolyTraitRef, TraitBoundModifier),
|
||||||
Outlives(Lifetime)
|
Outlives(Lifetime),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericBound {
|
impl GenericBound {
|
||||||
|
@ -304,7 +312,7 @@ pub enum GenericParamKind {
|
||||||
Lifetime,
|
Lifetime,
|
||||||
Type {
|
Type {
|
||||||
default: Option<P<Ty>>,
|
default: Option<P<Ty>>,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
|
@ -328,7 +336,7 @@ pub struct Generics {
|
||||||
|
|
||||||
impl Default for Generics {
|
impl Default for Generics {
|
||||||
/// Creates an instance of `Generics`.
|
/// Creates an instance of `Generics`.
|
||||||
fn default() -> Generics {
|
fn default() -> Generics {
|
||||||
Generics {
|
Generics {
|
||||||
params: Vec::new(),
|
params: Vec::new(),
|
||||||
where_clause: WhereClause {
|
where_clause: WhereClause {
|
||||||
|
@ -458,7 +466,7 @@ pub enum MetaItemKind {
|
||||||
/// Name value meta item.
|
/// Name value meta item.
|
||||||
///
|
///
|
||||||
/// E.g. `feature = "foo"` as in `#[feature = "foo"]`
|
/// E.g. `feature = "foo"` as in `#[feature = "foo"]`
|
||||||
NameValue(Lit)
|
NameValue(Lit),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Block (`{ .. }`).
|
/// A Block (`{ .. }`).
|
||||||
|
@ -492,14 +500,17 @@ impl Pat {
|
||||||
pub(super) fn to_ty(&self) -> Option<P<Ty>> {
|
pub(super) fn to_ty(&self) -> Option<P<Ty>> {
|
||||||
let node = match &self.node {
|
let node = match &self.node {
|
||||||
PatKind::Wild => TyKind::Infer,
|
PatKind::Wild => TyKind::Infer,
|
||||||
PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) =>
|
PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) => {
|
||||||
TyKind::Path(None, Path::from_ident(*ident)),
|
TyKind::Path(None, Path::from_ident(*ident))
|
||||||
|
}
|
||||||
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
|
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
|
||||||
PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
|
PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
|
||||||
PatKind::Ref(pat, mutbl) =>
|
PatKind::Ref(pat, mutbl) => pat
|
||||||
pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
|
.to_ty()
|
||||||
PatKind::Slice(pats, None, _) if pats.len() == 1 =>
|
.map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
|
||||||
pats[0].to_ty().map(TyKind::Slice)?,
|
PatKind::Slice(pats, None, _) if pats.len() == 1 => {
|
||||||
|
pats[0].to_ty().map(TyKind::Slice)?
|
||||||
|
}
|
||||||
PatKind::Tuple(pats, None) => {
|
PatKind::Tuple(pats, None) => {
|
||||||
let mut tys = Vec::with_capacity(pats.len());
|
let mut tys = Vec::with_capacity(pats.len());
|
||||||
// FIXME(#48994) - could just be collected into an Option<Vec>
|
// FIXME(#48994) - could just be collected into an Option<Vec>
|
||||||
|
@ -511,11 +522,16 @@ impl Pat {
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(P(Ty { node, id: self.id, span: self.span }))
|
Some(P(Ty {
|
||||||
|
node,
|
||||||
|
id: self.id,
|
||||||
|
span: self.span,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk<F>(&self, it: &mut F) -> bool
|
pub fn walk<F>(&self, it: &mut F) -> bool
|
||||||
where F: FnMut(&Pat) -> bool
|
where
|
||||||
|
F: FnMut(&Pat) -> bool,
|
||||||
{
|
{
|
||||||
if !it(self) {
|
if !it(self) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -523,28 +539,22 @@ impl Pat {
|
||||||
|
|
||||||
match self.node {
|
match self.node {
|
||||||
PatKind::Ident(_, _, Some(ref p)) => p.walk(it),
|
PatKind::Ident(_, _, Some(ref p)) => p.walk(it),
|
||||||
PatKind::Struct(_, ref fields, _) => {
|
PatKind::Struct(_, ref fields, _) => fields.iter().all(|field| field.node.pat.walk(it)),
|
||||||
fields.iter().all(|field| field.node.pat.walk(it))
|
|
||||||
}
|
|
||||||
PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
|
PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
|
||||||
s.iter().all(|p| p.walk(it))
|
s.iter().all(|p| p.walk(it))
|
||||||
}
|
}
|
||||||
PatKind::Box(ref s) | PatKind::Ref(ref s, _) | PatKind::Paren(ref s) => {
|
PatKind::Box(ref s) | PatKind::Ref(ref s, _) | PatKind::Paren(ref s) => s.walk(it),
|
||||||
s.walk(it)
|
|
||||||
}
|
|
||||||
PatKind::Slice(ref before, ref slice, ref after) => {
|
PatKind::Slice(ref before, ref slice, ref after) => {
|
||||||
before.iter().all(|p| p.walk(it)) &&
|
before.iter().all(|p| p.walk(it))
|
||||||
slice.iter().all(|p| p.walk(it)) &&
|
&& slice.iter().all(|p| p.walk(it))
|
||||||
after.iter().all(|p| p.walk(it))
|
&& after.iter().all(|p| p.walk(it))
|
||||||
}
|
|
||||||
PatKind::Wild |
|
|
||||||
PatKind::Lit(_) |
|
|
||||||
PatKind::Range(..) |
|
|
||||||
PatKind::Ident(..) |
|
|
||||||
PatKind::Path(..) |
|
|
||||||
PatKind::Mac(_) => {
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
PatKind::Wild
|
||||||
|
| PatKind::Lit(_)
|
||||||
|
| PatKind::Range(..)
|
||||||
|
| PatKind::Ident(..)
|
||||||
|
| PatKind::Path(..)
|
||||||
|
| PatKind::Mac(_) => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -623,13 +633,15 @@ pub enum PatKind {
|
||||||
/// `[a, b, ..i, y, z]` is represented as:
|
/// `[a, b, ..i, y, z]` is represented as:
|
||||||
/// `PatKind::Slice(box [a, b], Some(i), box [y, z])`
|
/// `PatKind::Slice(box [a, b], Some(i), box [y, z])`
|
||||||
Slice(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
|
Slice(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
|
||||||
/// Parentheses in patters used for grouping, i.e. `(PAT)`.
|
/// Parentheses in patterns used for grouping, i.e. `(PAT)`.
|
||||||
Paren(P<Pat>),
|
Paren(P<Pat>),
|
||||||
/// A macro pattern; pre-expansion
|
/// A macro pattern; pre-expansion
|
||||||
Mac(Mac),
|
Mac(Mac),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
|
#[derive(
|
||||||
|
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy,
|
||||||
|
)]
|
||||||
pub enum Mutability {
|
pub enum Mutability {
|
||||||
Mutable,
|
Mutable,
|
||||||
Immutable,
|
Immutable,
|
||||||
|
@ -702,25 +714,22 @@ impl BinOpKind {
|
||||||
pub fn lazy(&self) -> bool {
|
pub fn lazy(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
BinOpKind::And | BinOpKind::Or => true,
|
BinOpKind::And | BinOpKind::Or => true,
|
||||||
_ => false
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_shift(&self) -> bool {
|
pub fn is_shift(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
BinOpKind::Shl | BinOpKind::Shr => true,
|
BinOpKind::Shl | BinOpKind::Shr => true,
|
||||||
_ => false
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_comparison(&self) -> bool {
|
pub fn is_comparison(&self) -> bool {
|
||||||
use self::BinOpKind::*;
|
use self::BinOpKind::*;
|
||||||
match *self {
|
match *self {
|
||||||
Eq | Lt | Le | Ne | Gt | Ge =>
|
Eq | Lt | Le | Ne | Gt | Ge => true,
|
||||||
true,
|
And | Or | Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Shl | Shr => false,
|
||||||
And | Or | Add | Sub | Mul | Div | Rem |
|
|
||||||
BitXor | BitAnd | BitOr | Shl | Shr =>
|
|
||||||
false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,9 +781,9 @@ impl Stmt {
|
||||||
pub fn add_trailing_semicolon(mut self) -> Self {
|
pub fn add_trailing_semicolon(mut self) -> Self {
|
||||||
self.node = match self.node {
|
self.node = match self.node {
|
||||||
StmtKind::Expr(expr) => StmtKind::Semi(expr),
|
StmtKind::Expr(expr) => StmtKind::Semi(expr),
|
||||||
StmtKind::Mac(mac) => StmtKind::Mac(mac.map(|(mac, _style, attrs)| {
|
StmtKind::Mac(mac) => {
|
||||||
(mac, MacStmtStyle::Semicolon, attrs)
|
StmtKind::Mac(mac.map(|(mac, _style, attrs)| (mac, MacStmtStyle::Semicolon, attrs)))
|
||||||
})),
|
}
|
||||||
node => node,
|
node => node,
|
||||||
};
|
};
|
||||||
self
|
self
|
||||||
|
@ -797,11 +806,15 @@ impl Stmt {
|
||||||
|
|
||||||
impl fmt::Debug for Stmt {
|
impl fmt::Debug for Stmt {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "stmt({}: {})", self.id.to_string(), pprust::stmt_to_string(self))
|
write!(
|
||||||
|
f,
|
||||||
|
"stmt({}: {})",
|
||||||
|
self.id.to_string(),
|
||||||
|
pprust::stmt_to_string(self)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub enum StmtKind {
|
pub enum StmtKind {
|
||||||
/// A local (let) binding.
|
/// A local (let) binding.
|
||||||
|
@ -900,14 +913,13 @@ pub struct AnonConst {
|
||||||
pub value: P<Expr>,
|
pub value: P<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// An expression
|
/// An expression
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub struct Expr {
|
pub struct Expr {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
pub node: ExprKind,
|
pub node: ExprKind,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub attrs: ThinVec<Attribute>
|
pub attrs: ThinVec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expr {
|
impl Expr {
|
||||||
|
@ -937,9 +949,10 @@ impl Expr {
|
||||||
|
|
||||||
fn to_bound(&self) -> Option<GenericBound> {
|
fn to_bound(&self) -> Option<GenericBound> {
|
||||||
match &self.node {
|
match &self.node {
|
||||||
ExprKind::Path(None, path) =>
|
ExprKind::Path(None, path) => Some(GenericBound::Trait(
|
||||||
Some(GenericBound::Trait(PolyTraitRef::new(Vec::new(), path.clone(), self.span),
|
PolyTraitRef::new(Vec::new(), path.clone(), self.span),
|
||||||
TraitBoundModifier::None)),
|
TraitBoundModifier::None,
|
||||||
|
)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -949,26 +962,35 @@ impl Expr {
|
||||||
ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
|
ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
|
||||||
ExprKind::Mac(mac) => TyKind::Mac(mac.clone()),
|
ExprKind::Mac(mac) => TyKind::Mac(mac.clone()),
|
||||||
ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?,
|
ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?,
|
||||||
ExprKind::AddrOf(mutbl, expr) =>
|
ExprKind::AddrOf(mutbl, expr) => expr
|
||||||
expr.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
|
.to_ty()
|
||||||
ExprKind::Repeat(expr, expr_len) =>
|
.map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
|
||||||
expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))?,
|
ExprKind::Repeat(expr, expr_len) => {
|
||||||
ExprKind::Array(exprs) if exprs.len() == 1 =>
|
expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))?
|
||||||
exprs[0].to_ty().map(TyKind::Slice)?,
|
}
|
||||||
|
ExprKind::Array(exprs) if exprs.len() == 1 => exprs[0].to_ty().map(TyKind::Slice)?,
|
||||||
ExprKind::Tup(exprs) => {
|
ExprKind::Tup(exprs) => {
|
||||||
let tys = exprs.iter().map(|expr| expr.to_ty()).collect::<Option<Vec<_>>>()?;
|
let tys = exprs
|
||||||
|
.iter()
|
||||||
|
.map(|expr| expr.to_ty())
|
||||||
|
.collect::<Option<Vec<_>>>()?;
|
||||||
TyKind::Tup(tys)
|
TyKind::Tup(tys)
|
||||||
}
|
}
|
||||||
ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add =>
|
ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => {
|
||||||
if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) {
|
if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) {
|
||||||
TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
|
TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(P(Ty { node, id: self.id, span: self.span }))
|
Some(P(Ty {
|
||||||
|
node,
|
||||||
|
id: self.id,
|
||||||
|
span: self.span,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn precedence(&self) -> ExprPrecedence {
|
pub fn precedence(&self) -> ExprPrecedence {
|
||||||
|
@ -1195,7 +1217,7 @@ pub struct QSelf {
|
||||||
/// a::b::Trait>::AssociatedItem`; in the case where `position ==
|
/// a::b::Trait>::AssociatedItem`; in the case where `position ==
|
||||||
/// 0`, this is an empty span.
|
/// 0`, this is an empty span.
|
||||||
pub path_span: Span,
|
pub path_span: Span,
|
||||||
pub position: usize
|
pub position: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A capture clause
|
/// A capture clause
|
||||||
|
@ -1259,7 +1281,7 @@ pub enum StrStyle {
|
||||||
/// A raw string, like `r##"foo"##`
|
/// A raw string, like `r##"foo"##`
|
||||||
///
|
///
|
||||||
/// The value is the number of `#` symbols used.
|
/// The value is the number of `#` symbols used.
|
||||||
Raw(u16)
|
Raw(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A literal
|
/// A literal
|
||||||
|
@ -1307,9 +1329,7 @@ impl LitKind {
|
||||||
/// Returns true if this is a numeric literal.
|
/// Returns true if this is a numeric literal.
|
||||||
pub fn is_numeric(&self) -> bool {
|
pub fn is_numeric(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
LitKind::Int(..) |
|
LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => true,
|
||||||
LitKind::Float(..) |
|
|
||||||
LitKind::FloatUnsuffixed(..) => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1319,17 +1339,17 @@ impl LitKind {
|
||||||
pub fn is_unsuffixed(&self) -> bool {
|
pub fn is_unsuffixed(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
// unsuffixed variants
|
// unsuffixed variants
|
||||||
LitKind::Str(..) |
|
LitKind::Str(..)
|
||||||
LitKind::ByteStr(..) |
|
| LitKind::ByteStr(..)
|
||||||
LitKind::Byte(..) |
|
| LitKind::Byte(..)
|
||||||
LitKind::Char(..) |
|
| LitKind::Char(..)
|
||||||
LitKind::Int(_, LitIntType::Unsuffixed) |
|
| LitKind::Int(_, LitIntType::Unsuffixed)
|
||||||
LitKind::FloatUnsuffixed(..) |
|
| LitKind::FloatUnsuffixed(..)
|
||||||
LitKind::Bool(..) => true,
|
| LitKind::Bool(..) => true,
|
||||||
// suffixed variants
|
// suffixed variants
|
||||||
LitKind::Int(_, LitIntType::Signed(..)) |
|
LitKind::Int(_, LitIntType::Signed(..))
|
||||||
LitKind::Int(_, LitIntType::Unsigned(..)) |
|
| LitKind::Int(_, LitIntType::Unsigned(..))
|
||||||
LitKind::Float(..) => false,
|
| LitKind::Float(..) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1532,7 +1552,7 @@ pub struct BareFnTy {
|
||||||
pub unsafety: Unsafety,
|
pub unsafety: Unsafety,
|
||||||
pub abi: Abi,
|
pub abi: Abi,
|
||||||
pub generic_params: Vec<GenericParam>,
|
pub generic_params: Vec<GenericParam>,
|
||||||
pub decl: P<FnDecl>
|
pub decl: P<FnDecl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The different kinds of types recognized by the compiler
|
/// The different kinds of types recognized by the compiler
|
||||||
|
@ -1551,7 +1571,7 @@ pub enum TyKind {
|
||||||
/// The never type (`!`)
|
/// The never type (`!`)
|
||||||
Never,
|
Never,
|
||||||
/// A tuple (`(A, B, C, D,...)`)
|
/// A tuple (`(A, B, C, D,...)`)
|
||||||
Tup(Vec<P<Ty>> ),
|
Tup(Vec<P<Ty>>),
|
||||||
/// A path (`module::module::...::Type`), optionally
|
/// A path (`module::module::...::Type`), optionally
|
||||||
/// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
|
/// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
|
||||||
///
|
///
|
||||||
|
@ -1584,11 +1604,19 @@ pub enum TyKind {
|
||||||
|
|
||||||
impl TyKind {
|
impl TyKind {
|
||||||
pub fn is_implicit_self(&self) -> bool {
|
pub fn is_implicit_self(&self) -> bool {
|
||||||
if let TyKind::ImplicitSelf = *self { true } else { false }
|
if let TyKind::ImplicitSelf = *self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_unit(&self) -> bool {
|
pub fn is_unit(&self) -> bool {
|
||||||
if let TyKind::Tup(ref tys) = *self { tys.is_empty() } else { false }
|
if let TyKind::Tup(ref tys) = *self {
|
||||||
|
tys.is_empty()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1666,12 +1694,14 @@ impl Arg {
|
||||||
if ident.name == keywords::SelfValue.name() {
|
if ident.name == keywords::SelfValue.name() {
|
||||||
return match self.ty.node {
|
return match self.ty.node {
|
||||||
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
|
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
|
||||||
TyKind::Rptr(lt, MutTy{ref ty, mutbl}) if ty.node.is_implicit_self() => {
|
TyKind::Rptr(lt, MutTy { ref ty, mutbl }) if ty.node.is_implicit_self() => {
|
||||||
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
|
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
|
||||||
}
|
}
|
||||||
_ => Some(respan(self.pat.span.to(self.ty.span),
|
_ => Some(respan(
|
||||||
SelfKind::Explicit(self.ty.clone(), mutbl))),
|
self.pat.span.to(self.ty.span),
|
||||||
}
|
SelfKind::Explicit(self.ty.clone(), mutbl),
|
||||||
|
)),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
@ -1704,11 +1734,20 @@ impl Arg {
|
||||||
match eself.node {
|
match eself.node {
|
||||||
SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty),
|
SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty),
|
||||||
SelfKind::Value(mutbl) => arg(mutbl, infer_ty),
|
SelfKind::Value(mutbl) => arg(mutbl, infer_ty),
|
||||||
SelfKind::Region(lt, mutbl) => arg(Mutability::Immutable, P(Ty {
|
SelfKind::Region(lt, mutbl) => arg(
|
||||||
id: DUMMY_NODE_ID,
|
Mutability::Immutable,
|
||||||
node: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl: mutbl }),
|
P(Ty {
|
||||||
span,
|
id: DUMMY_NODE_ID,
|
||||||
})),
|
node: TyKind::Rptr(
|
||||||
|
lt,
|
||||||
|
MutTy {
|
||||||
|
ty: infer_ty,
|
||||||
|
mutbl: mutbl,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
span,
|
||||||
|
}),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1720,7 +1759,7 @@ impl Arg {
|
||||||
pub struct FnDecl {
|
pub struct FnDecl {
|
||||||
pub inputs: Vec<Arg>,
|
pub inputs: Vec<Arg>,
|
||||||
pub output: FunctionRetTy,
|
pub output: FunctionRetTy,
|
||||||
pub variadic: bool
|
pub variadic: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FnDecl {
|
impl FnDecl {
|
||||||
|
@ -1736,7 +1775,7 @@ impl FnDecl {
|
||||||
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub enum IsAuto {
|
pub enum IsAuto {
|
||||||
Yes,
|
Yes,
|
||||||
No
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
|
||||||
|
@ -1765,7 +1804,10 @@ impl IsAsync {
|
||||||
/// In case this is an `Async` return the `NodeId` for the generated impl Trait item
|
/// In case this is an `Async` return the `NodeId` for the generated impl Trait item
|
||||||
pub fn opt_return_id(self) -> Option<NodeId> {
|
pub fn opt_return_id(self) -> Option<NodeId> {
|
||||||
match self {
|
match self {
|
||||||
IsAsync::Async { return_impl_trait_id, .. } => Some(return_impl_trait_id),
|
IsAsync::Async {
|
||||||
|
return_impl_trait_id,
|
||||||
|
..
|
||||||
|
} => Some(return_impl_trait_id),
|
||||||
IsAsync::NotAsync => None,
|
IsAsync::NotAsync => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1785,10 +1827,13 @@ pub enum Defaultness {
|
||||||
|
|
||||||
impl fmt::Display for Unsafety {
|
impl fmt::Display for Unsafety {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Display::fmt(match *self {
|
fmt::Display::fmt(
|
||||||
Unsafety::Normal => "normal",
|
match *self {
|
||||||
Unsafety::Unsafe => "unsafe",
|
Unsafety::Normal => "normal",
|
||||||
}, f)
|
Unsafety::Unsafe => "unsafe",
|
||||||
|
},
|
||||||
|
f,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1809,7 +1854,6 @@ impl fmt::Debug for ImplPolarity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub enum FunctionRetTy {
|
pub enum FunctionRetTy {
|
||||||
/// Return type is not specified.
|
/// Return type is not specified.
|
||||||
|
@ -1904,8 +1948,13 @@ impl UseTree {
|
||||||
pub fn ident(&self) -> Ident {
|
pub fn ident(&self) -> Ident {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
UseTreeKind::Simple(Some(rename), ..) => rename,
|
UseTreeKind::Simple(Some(rename), ..) => rename,
|
||||||
UseTreeKind::Simple(None, ..) =>
|
UseTreeKind::Simple(None, ..) => {
|
||||||
self.prefix.segments.last().expect("empty prefix in a simple import").ident,
|
self.prefix
|
||||||
|
.segments
|
||||||
|
.last()
|
||||||
|
.expect("empty prefix in a simple import")
|
||||||
|
.ident
|
||||||
|
}
|
||||||
_ => panic!("`UseTree::ident` can only be used on a simple import"),
|
_ => panic!("`UseTree::ident` can only be used on a simple import"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1920,7 +1969,9 @@ pub enum AttrStyle {
|
||||||
Inner,
|
Inner,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, PartialOrd, Ord, Copy)]
|
#[derive(
|
||||||
|
Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, PartialOrd, Ord, Copy,
|
||||||
|
)]
|
||||||
pub struct AttrId(pub usize);
|
pub struct AttrId(pub usize);
|
||||||
|
|
||||||
impl Idx for AttrId {
|
impl Idx for AttrId {
|
||||||
|
@ -1971,7 +2022,10 @@ impl PolyTraitRef {
|
||||||
pub fn new(generic_params: Vec<GenericParam>, path: Path, span: Span) -> Self {
|
pub fn new(generic_params: Vec<GenericParam>, path: Path, span: Span) -> Self {
|
||||||
PolyTraitRef {
|
PolyTraitRef {
|
||||||
bound_generic_params: generic_params,
|
bound_generic_params: generic_params,
|
||||||
trait_ref: TraitRef { path: path, ref_id: DUMMY_NODE_ID },
|
trait_ref: TraitRef {
|
||||||
|
path: path,
|
||||||
|
ref_id: DUMMY_NODE_ID,
|
||||||
|
},
|
||||||
span,
|
span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1998,7 +2052,11 @@ pub enum VisibilityKind {
|
||||||
|
|
||||||
impl VisibilityKind {
|
impl VisibilityKind {
|
||||||
pub fn is_pub(&self) -> bool {
|
pub fn is_pub(&self) -> bool {
|
||||||
if let VisibilityKind::Public = *self { true } else { false }
|
if let VisibilityKind::Public = *self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2051,17 +2109,29 @@ impl VariantData {
|
||||||
}
|
}
|
||||||
pub fn id(&self) -> NodeId {
|
pub fn id(&self) -> NodeId {
|
||||||
match *self {
|
match *self {
|
||||||
VariantData::Struct(_, id) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id
|
VariantData::Struct(_, id) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn is_struct(&self) -> bool {
|
pub fn is_struct(&self) -> bool {
|
||||||
if let VariantData::Struct(..) = *self { true } else { false }
|
if let VariantData::Struct(..) = *self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn is_tuple(&self) -> bool {
|
pub fn is_tuple(&self) -> bool {
|
||||||
if let VariantData::Tuple(..) = *self { true } else { false }
|
if let VariantData::Tuple(..) = *self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn is_unit(&self) -> bool {
|
pub fn is_unit(&self) -> bool {
|
||||||
if let VariantData::Unit(..) = *self { true } else { false }
|
if let VariantData::Unit(..) = *self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2173,13 +2243,15 @@ pub enum ItemKind {
|
||||||
/// An implementation.
|
/// An implementation.
|
||||||
///
|
///
|
||||||
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
|
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
|
||||||
Impl(Unsafety,
|
Impl(
|
||||||
ImplPolarity,
|
Unsafety,
|
||||||
Defaultness,
|
ImplPolarity,
|
||||||
Generics,
|
Defaultness,
|
||||||
Option<TraitRef>, // (optional) trait this impl implements
|
Generics,
|
||||||
P<Ty>, // self
|
Option<TraitRef>, // (optional) trait this impl implements
|
||||||
Vec<ImplItem>),
|
P<Ty>, // self
|
||||||
|
Vec<ImplItem>,
|
||||||
|
),
|
||||||
/// A macro invocation.
|
/// A macro invocation.
|
||||||
///
|
///
|
||||||
/// E.g. `macro_rules! foo { .. }` or `foo!(..)`
|
/// E.g. `macro_rules! foo { .. }` or `foo!(..)`
|
||||||
|
@ -2207,9 +2279,7 @@ impl ItemKind {
|
||||||
ItemKind::Union(..) => "union",
|
ItemKind::Union(..) => "union",
|
||||||
ItemKind::Trait(..) => "trait",
|
ItemKind::Trait(..) => "trait",
|
||||||
ItemKind::TraitAlias(..) => "trait alias",
|
ItemKind::TraitAlias(..) => "trait alias",
|
||||||
ItemKind::Mac(..) |
|
ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl(..) => "item",
|
||||||
ItemKind::MacroDef(..) |
|
|
||||||
ItemKind::Impl(..) => "item"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2251,8 +2321,8 @@ impl ForeignItemKind {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serialize;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use serialize;
|
||||||
|
|
||||||
// are ASTs encodable?
|
// are ASTs encodable?
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -415,9 +415,6 @@ declare_features! (
|
||||||
// Multiple patterns with `|` in `if let` and `while let`
|
// Multiple patterns with `|` in `if let` and `while let`
|
||||||
(active, if_while_or_patterns, "1.26.0", Some(48215), None),
|
(active, if_while_or_patterns, "1.26.0", Some(48215), None),
|
||||||
|
|
||||||
// Parentheses in patterns
|
|
||||||
(active, pattern_parentheses, "1.26.0", Some(51087), None),
|
|
||||||
|
|
||||||
// Allows `#[repr(packed)]` attribute on structs
|
// Allows `#[repr(packed)]` attribute on structs
|
||||||
(active, repr_packed, "1.26.0", Some(33158), None),
|
(active, repr_packed, "1.26.0", Some(33158), None),
|
||||||
|
|
||||||
|
@ -686,6 +683,8 @@ declare_features! (
|
||||||
(accepted, extern_absolute_paths, "1.30.0", Some(44660), None),
|
(accepted, extern_absolute_paths, "1.30.0", Some(44660), None),
|
||||||
// Access to crate names passed via `--extern` through prelude
|
// Access to crate names passed via `--extern` through prelude
|
||||||
(accepted, extern_prelude, "1.30.0", Some(44660), None),
|
(accepted, extern_prelude, "1.30.0", Some(44660), None),
|
||||||
|
// Parentheses in patterns
|
||||||
|
(accepted, pattern_parentheses, "1.31.0", Some(51087), None),
|
||||||
);
|
);
|
||||||
|
|
||||||
// If you change this, please modify src/doc/unstable-book as well. You must
|
// If you change this, please modify src/doc/unstable-book as well. You must
|
||||||
|
@ -1791,10 +1790,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
|
gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
|
||||||
"exclusive range pattern syntax is experimental");
|
"exclusive range pattern syntax is experimental");
|
||||||
}
|
}
|
||||||
PatKind::Paren(..) => {
|
|
||||||
gate_feature_post!(&self, pattern_parentheses, pattern.span,
|
|
||||||
"parentheses in patterns are unstable");
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
visit::walk_pat(self, pattern)
|
visit::walk_pat(self, pattern)
|
||||||
|
|
|
@ -284,9 +284,7 @@ fn run() {
|
||||||
reject_stmt_parse("#[attr] #![attr] foo!{}");
|
reject_stmt_parse("#[attr] #![attr] foo!{}");
|
||||||
|
|
||||||
// FIXME: Allow attributes in pattern constexprs?
|
// FIXME: Allow attributes in pattern constexprs?
|
||||||
// would require parens in patterns to allow disambiguation...
|
// note: requires parens in patterns to allow disambiguation
|
||||||
// —which is now available under the `pattern_parentheses` feature gate
|
|
||||||
// (tracking issue #51087)
|
|
||||||
|
|
||||||
reject_expr_parse("match 0 {
|
reject_expr_parse("match 0 {
|
||||||
0..=#[attr] 10 => ()
|
0..=#[attr] 10 => ()
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
match 0 {
|
|
||||||
(pat) => {} //~ ERROR parentheses in patterns are unstable
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
error[E0658]: parentheses in patterns are unstable (see issue #51087)
|
|
||||||
--> $DIR/feature-gate-pattern_parentheses.rs:13:9
|
|
||||||
|
|
|
||||||
LL | (pat) => {} //~ ERROR parentheses in patterns are unstable
|
|
||||||
| ^^^^^
|
|
||||||
|
|
|
||||||
= help: add #![feature(pattern_parentheses)] to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
|
|
@ -9,7 +9,6 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// run-pass
|
// run-pass
|
||||||
#![feature(pattern_parentheses)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match 0 {
|
match 0 {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// run-pass
|
// run-pass
|
||||||
#![feature(box_patterns, pattern_parentheses)]
|
#![feature(box_patterns)]
|
||||||
|
|
||||||
const VALUE: usize = 21;
|
const VALUE: usize = 21;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue