Auto merge of #33864 - Manishearth:breaking-batch, r=Manishearth
Batch up libsyntax breaking changes cc https://github.com/rust-lang/rust/issues/31645
This commit is contained in:
commit
36d5dc7c9b
@ -2433,6 +2433,8 @@ The currently implemented features of the reference compiler are:
|
||||
* - `abi_vectorcall` - Allows the usage of the vectorcall calling convention
|
||||
(e.g. `extern "vectorcall" func fn_();`)
|
||||
|
||||
* - `dotdot_in_tuple_patterns` - Allows `..` in tuple (struct) patterns.
|
||||
|
||||
If a feature is promoted to a language feature, then all existing programs will
|
||||
start to receive compilation warnings about `#![feature]` directives which enabled
|
||||
the new feature (because the directive is no longer necessary). However, if a
|
||||
|
@ -100,7 +100,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
|
||||
match pat.node {
|
||||
PatKind::Ident(_, _, None) |
|
||||
PatKind::TupleStruct(_, None) |
|
||||
PatKind::Path(..) |
|
||||
PatKind::QPath(..) |
|
||||
PatKind::Lit(..) |
|
||||
@ -116,8 +115,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
self.add_ast_node(pat.id, &[subpat_exit])
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(_, Some(ref subpats)) |
|
||||
PatKind::Tup(ref subpats) => {
|
||||
PatKind::TupleStruct(_, ref subpats, _) |
|
||||
PatKind::Tuple(ref subpats, _) => {
|
||||
let pats_exit = self.pats_all(subpats.iter(), pred);
|
||||
self.add_ast_node(pat.id, &[pats_exit])
|
||||
}
|
||||
|
@ -923,9 +923,9 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
|
||||
sub.map(|x| folder.fold_pat(x)))
|
||||
}
|
||||
PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)),
|
||||
PatKind::TupleStruct(pth, pats) => {
|
||||
PatKind::TupleStruct(pth, pats, ddpos) => {
|
||||
PatKind::TupleStruct(folder.fold_path(pth),
|
||||
pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
|
||||
pats.move_map(|x| folder.fold_pat(x)), ddpos)
|
||||
}
|
||||
PatKind::Path(pth) => {
|
||||
PatKind::Path(folder.fold_path(pth))
|
||||
@ -948,7 +948,9 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
|
||||
});
|
||||
PatKind::Struct(pth, fs, etc)
|
||||
}
|
||||
PatKind::Tup(elts) => PatKind::Tup(elts.move_map(|x| folder.fold_pat(x))),
|
||||
PatKind::Tuple(elts, ddpos) => {
|
||||
PatKind::Tuple(elts.move_map(|x| folder.fold_pat(x)), ddpos)
|
||||
}
|
||||
PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)),
|
||||
PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl),
|
||||
PatKind::Range(e1, e2) => {
|
||||
@ -1009,11 +1011,15 @@ pub fn noop_fold_expr<T: Folder>(Expr { id, node, span, attrs }: Expr, folder: &
|
||||
ExprWhile(cond, body, opt_name) => {
|
||||
ExprWhile(folder.fold_expr(cond),
|
||||
folder.fold_block(body),
|
||||
opt_name.map(|i| folder.fold_name(i)))
|
||||
opt_name.map(|label| {
|
||||
respan(folder.new_span(label.span), folder.fold_name(label.node))
|
||||
}))
|
||||
}
|
||||
ExprLoop(body, opt_name) => {
|
||||
ExprLoop(folder.fold_block(body),
|
||||
opt_name.map(|i| folder.fold_name(i)))
|
||||
opt_name.map(|label| {
|
||||
respan(folder.new_span(label.span), folder.fold_name(label.node))
|
||||
}))
|
||||
}
|
||||
ExprMatch(expr, arms, source) => {
|
||||
ExprMatch(folder.fold_expr(expr),
|
||||
|
@ -28,7 +28,7 @@
|
||||
use syntax::abi::Abi;
|
||||
use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
|
||||
use syntax::attr::ThinAttributesExt;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
use hir::*;
|
||||
|
||||
use std::cmp;
|
||||
@ -203,11 +203,17 @@ pub trait Visitor<'v> : Sized {
|
||||
}
|
||||
|
||||
pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
|
||||
for name in opt_name {
|
||||
if let Some(name) = opt_name {
|
||||
visitor.visit_name(span, name);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_opt_sp_name<'v, V: Visitor<'v>>(visitor: &mut V, opt_sp_name: &Option<Spanned<Name>>) {
|
||||
if let Some(ref sp_name) = *opt_sp_name {
|
||||
visitor.visit_name(sp_name.span, sp_name.node);
|
||||
}
|
||||
}
|
||||
|
||||
/// Walks the contents of a crate. See also `Crate::visit_all_items`.
|
||||
pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
|
||||
visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
|
||||
@ -454,11 +460,9 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
|
||||
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
|
||||
match pattern.node {
|
||||
PatKind::TupleStruct(ref path, ref opt_children) => {
|
||||
PatKind::TupleStruct(ref path, ref children, _) => {
|
||||
visitor.visit_path(path, pattern.id);
|
||||
if let Some(ref children) = *opt_children {
|
||||
walk_list!(visitor, visit_pat, children);
|
||||
}
|
||||
walk_list!(visitor, visit_pat, children);
|
||||
}
|
||||
PatKind::Path(ref path) => {
|
||||
visitor.visit_path(path, pattern.id);
|
||||
@ -474,7 +478,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
|
||||
visitor.visit_pat(&field.node.pat)
|
||||
}
|
||||
}
|
||||
PatKind::Tup(ref tuple_elements) => {
|
||||
PatKind::Tuple(ref tuple_elements, _) => {
|
||||
walk_list!(visitor, visit_pat, tuple_elements);
|
||||
}
|
||||
PatKind::Box(ref subpattern) |
|
||||
@ -737,14 +741,14 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||
visitor.visit_block(if_block);
|
||||
walk_list!(visitor, visit_expr, optional_else);
|
||||
}
|
||||
ExprWhile(ref subexpression, ref block, opt_name) => {
|
||||
ExprWhile(ref subexpression, ref block, ref opt_sp_name) => {
|
||||
visitor.visit_expr(subexpression);
|
||||
visitor.visit_block(block);
|
||||
walk_opt_name(visitor, expression.span, opt_name)
|
||||
walk_opt_sp_name(visitor, opt_sp_name);
|
||||
}
|
||||
ExprLoop(ref block, opt_name) => {
|
||||
ExprLoop(ref block, ref opt_sp_name) => {
|
||||
visitor.visit_block(block);
|
||||
walk_opt_name(visitor, expression.span, opt_name)
|
||||
walk_opt_sp_name(visitor, opt_sp_name);
|
||||
}
|
||||
ExprMatch(ref subexpression, ref arms, _) => {
|
||||
visitor.visit_expr(subexpression);
|
||||
@ -784,9 +788,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||
visitor.visit_path(path, expression.id)
|
||||
}
|
||||
ExprBreak(ref opt_sp_name) | ExprAgain(ref opt_sp_name) => {
|
||||
for sp_name in opt_sp_name {
|
||||
visitor.visit_name(sp_name.span, sp_name.node);
|
||||
}
|
||||
walk_opt_sp_name(visitor, opt_sp_name);
|
||||
}
|
||||
ExprRet(ref optional_expression) => {
|
||||
walk_list!(visitor, visit_expr, optional_expression);
|
||||
|
@ -192,6 +192,10 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
|
||||
o_id.map(|sp_ident| respan(sp_ident.span, self.lower_ident(sp_ident.node)))
|
||||
}
|
||||
|
||||
fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
|
||||
attrs.clone().into()
|
||||
}
|
||||
@ -269,7 +273,7 @@ impl<'a> LoweringContext<'a> {
|
||||
P(hir::Ty {
|
||||
id: t.id,
|
||||
node: match t.node {
|
||||
Infer => hir::TyInfer,
|
||||
Infer | ImplicitSelf => hir::TyInfer,
|
||||
Vec(ref ty) => hir::TyVec(self.lower_ty(ty)),
|
||||
Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
|
||||
Rptr(ref region, ref mt) => {
|
||||
@ -787,23 +791,24 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
|
||||
fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
|
||||
// Check for `self: _` and `self: &_`
|
||||
if let SelfKind::Explicit(ref ty, _) = sig.explicit_self.node {
|
||||
match sig.decl.inputs.get(0).and_then(Arg::to_self).map(|eself| eself.node) {
|
||||
Some(SelfKind::Value(..)) | Some(SelfKind::Region(..)) => {
|
||||
self.id_assigner.diagnostic().span_err(ty.span,
|
||||
"the type placeholder `_` is not allowed within types on item signatures");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
hir::MethodSig {
|
||||
let hir_sig = hir::MethodSig {
|
||||
generics: self.lower_generics(&sig.generics),
|
||||
abi: sig.abi,
|
||||
unsafety: self.lower_unsafety(sig.unsafety),
|
||||
constness: self.lower_constness(sig.constness),
|
||||
decl: self.lower_fn_decl(&sig.decl),
|
||||
};
|
||||
// Check for `self: _` and `self: &_`
|
||||
if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) {
|
||||
match hir_sig.decl.get_self().map(|eself| eself.node) {
|
||||
Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => {
|
||||
self.id_assigner.diagnostic().span_err(sig.decl.inputs[0].ty.span,
|
||||
"the type placeholder `_` is not allowed within types on item signatures");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
hir_sig
|
||||
}
|
||||
|
||||
fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
|
||||
@ -872,10 +877,10 @@ impl<'a> LoweringContext<'a> {
|
||||
})
|
||||
}
|
||||
PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
|
||||
PatKind::TupleStruct(ref pth, ref pats) => {
|
||||
PatKind::TupleStruct(ref pth, ref pats, ddpos) => {
|
||||
hir::PatKind::TupleStruct(self.lower_path(pth),
|
||||
pats.as_ref()
|
||||
.map(|pats| pats.iter().map(|x| self.lower_pat(x)).collect()))
|
||||
pats.iter().map(|x| self.lower_pat(x)).collect(),
|
||||
ddpos)
|
||||
}
|
||||
PatKind::Path(ref pth) => {
|
||||
hir::PatKind::Path(self.lower_path(pth))
|
||||
@ -903,8 +908,8 @@ impl<'a> LoweringContext<'a> {
|
||||
.collect();
|
||||
hir::PatKind::Struct(pth, fs, etc)
|
||||
}
|
||||
PatKind::Tup(ref elts) => {
|
||||
hir::PatKind::Tup(elts.iter().map(|x| self.lower_pat(x)).collect())
|
||||
PatKind::Tuple(ref elts, ddpos) => {
|
||||
hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
|
||||
}
|
||||
PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
|
||||
PatKind::Ref(ref inner, mutbl) => {
|
||||
@ -1122,11 +1127,10 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
ExprKind::While(ref cond, ref body, opt_ident) => {
|
||||
hir::ExprWhile(self.lower_expr(cond), self.lower_block(body),
|
||||
opt_ident.map(|ident| self.lower_ident(ident)))
|
||||
self.lower_opt_sp_ident(opt_ident))
|
||||
}
|
||||
ExprKind::Loop(ref body, opt_ident) => {
|
||||
hir::ExprLoop(self.lower_block(body),
|
||||
opt_ident.map(|ident| self.lower_ident(ident)))
|
||||
hir::ExprLoop(self.lower_block(body), self.lower_opt_sp_ident(opt_ident))
|
||||
}
|
||||
ExprKind::Match(ref expr, ref arms) => {
|
||||
hir::ExprMatch(self.lower_expr(expr),
|
||||
@ -1243,12 +1247,8 @@ impl<'a> LoweringContext<'a> {
|
||||
};
|
||||
hir::ExprPath(hir_qself, self.lower_path_full(path, rename))
|
||||
}
|
||||
ExprKind::Break(opt_ident) => hir::ExprBreak(opt_ident.map(|sp_ident| {
|
||||
respan(sp_ident.span, self.lower_ident(sp_ident.node))
|
||||
})),
|
||||
ExprKind::Again(opt_ident) => hir::ExprAgain(opt_ident.map(|sp_ident| {
|
||||
respan(sp_ident.span, self.lower_ident(sp_ident.node))
|
||||
})),
|
||||
ExprKind::Break(opt_ident) => hir::ExprBreak(self.lower_opt_sp_ident(opt_ident)),
|
||||
ExprKind::Again(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)),
|
||||
ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))),
|
||||
ExprKind::InlineAsm(InlineAsm {
|
||||
ref inputs,
|
||||
@ -1422,8 +1422,7 @@ impl<'a> LoweringContext<'a> {
|
||||
|
||||
// `[opt_ident]: loop { ... }`
|
||||
let loop_block = self.block_expr(match_expr);
|
||||
let loop_expr = hir::ExprLoop(loop_block,
|
||||
opt_ident.map(|ident| self.lower_ident(ident)));
|
||||
let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident));
|
||||
// add attributes to the outer returned expr node
|
||||
let attrs = e.attrs.clone();
|
||||
return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs });
|
||||
@ -1503,8 +1502,7 @@ impl<'a> LoweringContext<'a> {
|
||||
|
||||
// `[opt_ident]: loop { ... }`
|
||||
let loop_block = self.block_expr(match_expr);
|
||||
let loop_expr = hir::ExprLoop(loop_block,
|
||||
opt_ident.map(|ident| self.lower_ident(ident)));
|
||||
let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident));
|
||||
let loop_expr =
|
||||
P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None });
|
||||
|
||||
@ -1857,7 +1855,7 @@ impl<'a> LoweringContext<'a> {
|
||||
let pt = if subpats.is_empty() {
|
||||
hir::PatKind::Path(path)
|
||||
} else {
|
||||
hir::PatKind::TupleStruct(path, Some(subpats))
|
||||
hir::PatKind::TupleStruct(path, subpats, None)
|
||||
};
|
||||
let pat = self.pat(span, pt);
|
||||
self.resolver.record_resolution(pat.id, def);
|
||||
|
@ -470,7 +470,7 @@ impl Pat {
|
||||
PatKind::Struct(_, ref fields, _) => {
|
||||
fields.iter().all(|field| field.node.pat.walk_(it))
|
||||
}
|
||||
PatKind::TupleStruct(_, Some(ref s)) | PatKind::Tup(ref s) => {
|
||||
PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
|
||||
s.iter().all(|p| p.walk_(it))
|
||||
}
|
||||
PatKind::Box(ref s) | PatKind::Ref(ref s, _) => {
|
||||
@ -485,7 +485,6 @@ impl Pat {
|
||||
PatKind::Lit(_) |
|
||||
PatKind::Range(_, _) |
|
||||
PatKind::Ident(_, _, _) |
|
||||
PatKind::TupleStruct(..) |
|
||||
PatKind::Path(..) |
|
||||
PatKind::QPath(_, _) => {
|
||||
true
|
||||
@ -539,9 +538,10 @@ pub enum PatKind {
|
||||
/// The `bool` is `true` in the presence of a `..`.
|
||||
Struct(Path, HirVec<Spanned<FieldPat>>, bool),
|
||||
|
||||
/// A tuple struct/variant pattern `Variant(x, y, z)`.
|
||||
/// "None" means a `Variant(..)` pattern where we don't bind the fields to names.
|
||||
TupleStruct(Path, Option<HirVec<P<Pat>>>),
|
||||
/// A tuple struct/variant pattern `Variant(x, y, .., z)`.
|
||||
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
|
||||
/// 0 <= position <= subpats.len()
|
||||
TupleStruct(Path, HirVec<P<Pat>>, Option<usize>),
|
||||
|
||||
/// A path pattern.
|
||||
/// Such pattern can be resolved to a unit struct/variant or a constant.
|
||||
@ -553,8 +553,10 @@ pub enum PatKind {
|
||||
/// PatKind::Path, and the resolver will have to sort that out.
|
||||
QPath(QSelf, Path),
|
||||
|
||||
/// A tuple pattern `(a, b)`
|
||||
Tup(HirVec<P<Pat>>),
|
||||
/// A tuple pattern `(a, b)`.
|
||||
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
|
||||
/// 0 <= position <= subpats.len()
|
||||
Tuple(HirVec<P<Pat>>, Option<usize>),
|
||||
/// A `box` pattern
|
||||
Box(P<Pat>),
|
||||
/// A reference pattern, e.g. `&mut (a, b)`
|
||||
@ -873,11 +875,11 @@ pub enum Expr_ {
|
||||
/// A while loop, with an optional label
|
||||
///
|
||||
/// `'label: while expr { block }`
|
||||
ExprWhile(P<Expr>, P<Block>, Option<Name>),
|
||||
ExprWhile(P<Expr>, P<Block>, Option<Spanned<Name>>),
|
||||
/// Conditionless loop (can be exited with break, continue, or return)
|
||||
///
|
||||
/// `'label: loop { block }`
|
||||
ExprLoop(P<Block>, Option<Name>),
|
||||
ExprLoop(P<Block>, Option<Spanned<Name>>),
|
||||
/// A `match` block, with a source that indicates whether or not it is
|
||||
/// the result of a desugaring, and if so, which kind.
|
||||
ExprMatch(P<Expr>, HirVec<Arm>, MatchSource),
|
||||
@ -1175,6 +1177,9 @@ pub struct FnDecl {
|
||||
}
|
||||
|
||||
impl FnDecl {
|
||||
pub fn get_self(&self) -> Option<ExplicitSelf> {
|
||||
self.inputs.get(0).and_then(Arg::to_self)
|
||||
}
|
||||
pub fn has_self(&self) -> bool {
|
||||
self.inputs.get(0).map(Arg::is_self).unwrap_or(false)
|
||||
}
|
||||
|
@ -18,9 +18,43 @@ use hir::{self, PatKind};
|
||||
use syntax::codemap::{respan, Span, Spanned, DUMMY_SP};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::iter::{Enumerate, ExactSizeIterator};
|
||||
|
||||
pub type PatIdMap = FnvHashMap<ast::Name, ast::NodeId>;
|
||||
|
||||
pub struct EnumerateAndAdjust<I> {
|
||||
enumerate: Enumerate<I>,
|
||||
gap_pos: usize,
|
||||
gap_len: usize,
|
||||
}
|
||||
|
||||
impl<I> Iterator for EnumerateAndAdjust<I> where I: Iterator {
|
||||
type Item = (usize, <I as Iterator>::Item);
|
||||
|
||||
fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
|
||||
self.enumerate.next().map(|(i, elem)| {
|
||||
(if i < self.gap_pos { i } else { i + self.gap_len }, elem)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EnumerateAndAdjustIterator {
|
||||
fn enumerate_and_adjust(self, expected_len: usize, gap_pos: Option<usize>)
|
||||
-> EnumerateAndAdjust<Self> where Self: Sized;
|
||||
}
|
||||
|
||||
impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
|
||||
fn enumerate_and_adjust(self, expected_len: usize, gap_pos: Option<usize>)
|
||||
-> EnumerateAndAdjust<Self> where Self: Sized {
|
||||
let actual_len = self.len();
|
||||
EnumerateAndAdjust {
|
||||
enumerate: self.enumerate(),
|
||||
gap_pos: if let Some(gap_pos) = gap_pos { gap_pos } else { expected_len },
|
||||
gap_len: expected_len - actual_len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is used because same-named variables in alternative patterns need to
|
||||
// use the NodeId of their namesake in the first pattern.
|
||||
pub fn pat_id_map(dm: &RefCell<DefMap>, pat: &hir::Pat) -> PatIdMap {
|
||||
|
@ -1351,9 +1351,9 @@ impl<'a> State<'a> {
|
||||
hir::ExprIf(ref test, ref blk, ref elseopt) => {
|
||||
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
|
||||
}
|
||||
hir::ExprWhile(ref test, ref blk, opt_name) => {
|
||||
if let Some(name) = opt_name {
|
||||
self.print_name(name)?;
|
||||
hir::ExprWhile(ref test, ref blk, opt_sp_name) => {
|
||||
if let Some(sp_name) = opt_sp_name {
|
||||
self.print_name(sp_name.node)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("while")?;
|
||||
@ -1361,9 +1361,9 @@ impl<'a> State<'a> {
|
||||
space(&mut self.s)?;
|
||||
self.print_block(&blk)?;
|
||||
}
|
||||
hir::ExprLoop(ref blk, opt_name) => {
|
||||
if let Some(name) = opt_name {
|
||||
self.print_name(name)?;
|
||||
hir::ExprLoop(ref blk, opt_sp_name) => {
|
||||
if let Some(sp_name) = opt_sp_name {
|
||||
self.print_name(sp_name.node)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("loop")?;
|
||||
@ -1736,16 +1736,23 @@ impl<'a> State<'a> {
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
PatKind::TupleStruct(ref path, ref args_) => {
|
||||
PatKind::TupleStruct(ref path, ref elts, ddpos) => {
|
||||
self.print_path(path, true, 0)?;
|
||||
match *args_ {
|
||||
None => word(&mut self.s, "(..)")?,
|
||||
Some(ref args) => {
|
||||
self.popen()?;
|
||||
self.commasep(Inconsistent, &args[..], |s, p| s.print_pat(&p))?;
|
||||
self.pclose()?;
|
||||
self.popen()?;
|
||||
if let Some(ddpos) = ddpos {
|
||||
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
|
||||
if ddpos != 0 {
|
||||
self.word_space(",")?;
|
||||
}
|
||||
word(&mut self.s, "..")?;
|
||||
if ddpos != elts.len() {
|
||||
word(&mut self.s, ",")?;
|
||||
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
|
||||
}
|
||||
} else {
|
||||
try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)));
|
||||
}
|
||||
try!(self.pclose());
|
||||
}
|
||||
PatKind::Path(ref path) => {
|
||||
self.print_path(path, true, 0)?;
|
||||
@ -1778,11 +1785,23 @@ impl<'a> State<'a> {
|
||||
space(&mut self.s)?;
|
||||
word(&mut self.s, "}")?;
|
||||
}
|
||||
PatKind::Tup(ref elts) => {
|
||||
PatKind::Tuple(ref elts, ddpos) => {
|
||||
self.popen()?;
|
||||
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
|
||||
if elts.len() == 1 {
|
||||
word(&mut self.s, ",")?;
|
||||
if let Some(ddpos) = ddpos {
|
||||
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
|
||||
if ddpos != 0 {
|
||||
self.word_space(",")?;
|
||||
}
|
||||
word(&mut self.s, "..")?;
|
||||
if ddpos != elts.len() {
|
||||
word(&mut self.s, ",")?;
|
||||
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
|
||||
}
|
||||
} else {
|
||||
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
|
||||
if elts.len() == 1 {
|
||||
word(&mut self.s, ",")?;
|
||||
}
|
||||
}
|
||||
self.pclose()?;
|
||||
}
|
||||
|
@ -1043,11 +1043,6 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> {
|
||||
run_lints!(self, check_lifetime_def, early_passes, lt);
|
||||
}
|
||||
|
||||
fn visit_explicit_self(&mut self, es: &ast::ExplicitSelf) {
|
||||
run_lints!(self, check_explicit_self, early_passes, es);
|
||||
ast_visit::walk_explicit_self(self, es);
|
||||
}
|
||||
|
||||
fn visit_path(&mut self, p: &ast::Path, id: ast::NodeId) {
|
||||
run_lints!(self, check_path, early_passes, p, id);
|
||||
ast_visit::walk_path(self, p);
|
||||
|
@ -167,7 +167,6 @@ pub trait LateLintPass: LintPass {
|
||||
fn check_variant_post(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) { }
|
||||
fn check_lifetime(&mut self, _: &LateContext, _: &hir::Lifetime) { }
|
||||
fn check_lifetime_def(&mut self, _: &LateContext, _: &hir::LifetimeDef) { }
|
||||
fn check_explicit_self(&mut self, _: &LateContext, _: &hir::ExplicitSelf) { }
|
||||
fn check_path(&mut self, _: &LateContext, _: &hir::Path, _: ast::NodeId) { }
|
||||
fn check_path_list_item(&mut self, _: &LateContext, _: &hir::PathListItem) { }
|
||||
fn check_attribute(&mut self, _: &LateContext, _: &ast::Attribute) { }
|
||||
@ -218,7 +217,6 @@ pub trait EarlyLintPass: LintPass {
|
||||
fn check_variant_post(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { }
|
||||
fn check_lifetime(&mut self, _: &EarlyContext, _: &ast::Lifetime) { }
|
||||
fn check_lifetime_def(&mut self, _: &EarlyContext, _: &ast::LifetimeDef) { }
|
||||
fn check_explicit_self(&mut self, _: &EarlyContext, _: &ast::ExplicitSelf) { }
|
||||
fn check_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { }
|
||||
fn check_path_list_item(&mut self, _: &EarlyContext, _: &ast::PathListItem) { }
|
||||
fn check_attribute(&mut self, _: &EarlyContext, _: &ast::Attribute) { }
|
||||
|
@ -1127,7 +1127,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
// will visit the substructure recursively.
|
||||
}
|
||||
|
||||
PatKind::Wild | PatKind::Tup(..) | PatKind::Box(..) |
|
||||
PatKind::Wild | PatKind::Tuple(..) | PatKind::Box(..) |
|
||||
PatKind::Ref(..) | PatKind::Lit(..) | PatKind::Range(..) |
|
||||
PatKind::Vec(..) => {
|
||||
// Similarly, each of these cases does not
|
||||
|
@ -80,6 +80,7 @@ use ty::adjustment;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
|
||||
use hir::{MutImmutable, MutMutable, PatKind};
|
||||
use hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use hir;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
@ -1225,14 +1226,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
// _
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(_, None) => {
|
||||
// variant(..)
|
||||
}
|
||||
PatKind::TupleStruct(_, Some(ref subpats)) => {
|
||||
PatKind::TupleStruct(_, ref subpats, ddpos) => {
|
||||
match opt_def {
|
||||
Some(Def::Variant(..)) => {
|
||||
Some(Def::Variant(enum_def, def_id)) => {
|
||||
// variant(x, y, z)
|
||||
for (i, subpat) in subpats.iter().enumerate() {
|
||||
let expected_len = self.tcx().lookup_adt_def(enum_def)
|
||||
.variant_with_id(def_id).fields.len();
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
|
||||
|
||||
let subcmt =
|
||||
@ -1244,7 +1244,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
Some(Def::Struct(..)) => {
|
||||
for (i, subpat) in subpats.iter().enumerate() {
|
||||
let expected_len = match self.pat_ty(&pat) {
|
||||
Ok(&ty::TyS{sty: ty::TyStruct(adt_def, _), ..}) => {
|
||||
adt_def.struct_variant().fields.len()
|
||||
}
|
||||
ref ty => {
|
||||
span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
|
||||
}
|
||||
};
|
||||
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
|
||||
let cmt_field =
|
||||
self.cat_imm_interior(
|
||||
@ -1284,9 +1293,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Tup(ref subpats) => {
|
||||
PatKind::Tuple(ref subpats, ddpos) => {
|
||||
// (p1, ..., pN)
|
||||
for (i, subpat) in subpats.iter().enumerate() {
|
||||
let expected_len = match self.pat_ty(&pat) {
|
||||
Ok(&ty::TyS{sty: ty::TyTuple(ref tys), ..}) => tys.len(),
|
||||
ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
|
||||
};
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
|
||||
let subcmt =
|
||||
self.cat_imm_interior(
|
||||
|
@ -970,8 +970,8 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) {
|
||||
pats3.iter().any(|p| is_binding_pat(&p))
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(_, Some(ref subpats)) |
|
||||
PatKind::Tup(ref subpats) => {
|
||||
PatKind::TupleStruct(_, ref subpats, _) |
|
||||
PatKind::Tuple(ref subpats, _) => {
|
||||
subpats.iter().any(|p| is_binding_pat(&p))
|
||||
}
|
||||
|
||||
|
@ -404,23 +404,23 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
|
||||
if let hir::ExprClosure(..) = ex.node {
|
||||
return
|
||||
}
|
||||
if let Some(label) = expression_label(ex) {
|
||||
if let Some((label, label_span)) = expression_label(ex) {
|
||||
for &(prior, prior_span) in &self.labels_in_fn[..] {
|
||||
// FIXME (#24278): non-hygienic comparison
|
||||
if label == prior {
|
||||
signal_shadowing_problem(self.sess,
|
||||
label,
|
||||
original_label(prior_span),
|
||||
shadower_label(ex.span));
|
||||
shadower_label(label_span));
|
||||
}
|
||||
}
|
||||
|
||||
check_if_label_shadows_lifetime(self.sess,
|
||||
self.scope,
|
||||
label,
|
||||
ex.span);
|
||||
label_span);
|
||||
|
||||
self.labels_in_fn.push((label, ex.span));
|
||||
self.labels_in_fn.push((label, label_span));
|
||||
}
|
||||
intravisit::walk_expr(self, ex)
|
||||
}
|
||||
@ -430,10 +430,11 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
|
||||
}
|
||||
}
|
||||
|
||||
fn expression_label(ex: &hir::Expr) -> Option<ast::Name> {
|
||||
fn expression_label(ex: &hir::Expr) -> Option<(ast::Name, Span)> {
|
||||
match ex.node {
|
||||
hir::ExprWhile(_, _, Some(label)) |
|
||||
hir::ExprLoop(_, Some(label)) => Some(label.unhygienize()),
|
||||
hir::ExprLoop(_, Some(label)) => Some((label.node.unhygienize(),
|
||||
label.span)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
|
||||
use hir;
|
||||
use hir::{Item, Generics, StructField, Variant, PatKind};
|
||||
use hir::intravisit::{self, Visitor};
|
||||
use hir::pat_util::EnumerateAndAdjustIterator;
|
||||
|
||||
use std::mem::replace;
|
||||
use std::cmp::Ordering;
|
||||
@ -614,10 +615,9 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
|
||||
};
|
||||
match pat.node {
|
||||
// Foo(a, b, c)
|
||||
// A Variant(..) pattern `PatKind::TupleStruct(_, None)` doesn't have to be recursed into.
|
||||
PatKind::TupleStruct(_, Some(ref pat_fields)) => {
|
||||
for (field, struct_field) in pat_fields.iter().zip(&v.fields) {
|
||||
maybe_do_stability_check(tcx, struct_field.did, field.span, cb)
|
||||
PatKind::TupleStruct(_, ref pat_fields, ddpos) => {
|
||||
for (i, field) in pat_fields.iter().enumerate_and_adjust(v.fields.len(), ddpos) {
|
||||
maybe_do_stability_check(tcx, v.fields[i].did, field.span, cb)
|
||||
}
|
||||
}
|
||||
// Foo { a, b, c }
|
||||
|
@ -374,7 +374,7 @@ fn pat_is_catchall(dm: &DefMap, p: &Pat) -> bool {
|
||||
PatKind::Ident(_, _, None) => pat_is_binding(dm, p),
|
||||
PatKind::Ident(_, _, Some(ref s)) => pat_is_catchall(dm, &s),
|
||||
PatKind::Ref(ref s, _) => pat_is_catchall(dm, &s),
|
||||
PatKind::Tup(ref v) => v.iter().all(|p| pat_is_catchall(dm, &p)),
|
||||
PatKind::Tuple(ref v, _) => v.iter().all(|p| pat_is_catchall(dm, &p)),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
@ -398,7 +398,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir:
|
||||
hir::MatchSource::ForLoopDesugar => {
|
||||
// `witnesses[0]` has the form `Some(<head>)`, peel off the `Some`
|
||||
let witness = match witnesses[0].node {
|
||||
PatKind::TupleStruct(_, Some(ref pats)) => match &pats[..] {
|
||||
PatKind::TupleStruct(_, ref pats, _) => match &pats[..] {
|
||||
[ref pat] => &**pat,
|
||||
_ => bug!(),
|
||||
},
|
||||
@ -559,7 +559,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
|
||||
let pats_len = pats.len();
|
||||
let mut pats = pats.into_iter().map(|p| P((*p).clone()));
|
||||
let pat = match left_ty.sty {
|
||||
ty::TyTuple(_) => PatKind::Tup(pats.collect()),
|
||||
ty::TyTuple(..) => PatKind::Tuple(pats.collect(), None),
|
||||
|
||||
ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => {
|
||||
let v = ctor.variant_for_adt(adt);
|
||||
@ -580,7 +580,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
|
||||
PatKind::Struct(def_to_path(cx.tcx, v.did), field_pats, has_more_fields)
|
||||
}
|
||||
VariantKind::Tuple => {
|
||||
PatKind::TupleStruct(def_to_path(cx.tcx, v.did), Some(pats.collect()))
|
||||
PatKind::TupleStruct(def_to_path(cx.tcx, v.did), pats.collect(), None)
|
||||
}
|
||||
VariantKind::Unit => {
|
||||
PatKind::Path(def_to_path(cx.tcx, v.did))
|
||||
@ -832,7 +832,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
|
||||
vec!(Slice(before.len() + after.len()))
|
||||
}
|
||||
},
|
||||
PatKind::Box(_) | PatKind::Tup(_) | PatKind::Ref(..) =>
|
||||
PatKind::Box(..) | PatKind::Tuple(..) | PatKind::Ref(..) =>
|
||||
vec!(Single),
|
||||
PatKind::Wild =>
|
||||
vec!(),
|
||||
@ -914,7 +914,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(_, ref args) => {
|
||||
PatKind::TupleStruct(_, ref args, ddpos) => {
|
||||
let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
|
||||
match def {
|
||||
Def::Const(..) | Def::AssociatedConst(..) =>
|
||||
@ -922,10 +922,15 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
|
||||
been rewritten"),
|
||||
Def::Variant(_, id) if *constructor != Variant(id) => None,
|
||||
Def::Variant(..) | Def::Struct(..) => {
|
||||
Some(match args {
|
||||
&Some(ref args) => args.iter().map(|p| &**p).collect(),
|
||||
&None => vec![DUMMY_WILD_PAT; arity],
|
||||
})
|
||||
match ddpos {
|
||||
Some(ddpos) => {
|
||||
let mut pats: Vec<_> = args[..ddpos].iter().map(|p| &**p).collect();
|
||||
pats.extend(repeat(DUMMY_WILD_PAT).take(arity - args.len()));
|
||||
pats.extend(args[ddpos..].iter().map(|p| &**p));
|
||||
Some(pats)
|
||||
}
|
||||
None => Some(args.iter().map(|p| &**p).collect())
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
@ -952,7 +957,13 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Tup(ref args) =>
|
||||
PatKind::Tuple(ref args, Some(ddpos)) => {
|
||||
let mut pats: Vec<_> = args[..ddpos].iter().map(|p| &**p).collect();
|
||||
pats.extend(repeat(DUMMY_WILD_PAT).take(arity - args.len()));
|
||||
pats.extend(args[ddpos..].iter().map(|p| &**p));
|
||||
Some(pats)
|
||||
}
|
||||
PatKind::Tuple(ref args, None) =>
|
||||
Some(args.iter().map(|p| &**p).collect()),
|
||||
|
||||
PatKind::Box(ref inner) | PatKind::Ref(ref inner, _) =>
|
||||
|
@ -271,10 +271,9 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
let pat = match expr.node {
|
||||
hir::ExprTup(ref exprs) =>
|
||||
PatKind::Tup(try!(exprs.iter()
|
||||
.map(|expr| const_expr_to_pat(tcx, &expr,
|
||||
pat_id, span))
|
||||
.collect())),
|
||||
PatKind::Tuple(try!(exprs.iter()
|
||||
.map(|expr| const_expr_to_pat(tcx, &expr, pat_id, span))
|
||||
.collect()), None),
|
||||
|
||||
hir::ExprCall(ref callee, ref args) => {
|
||||
let def = *tcx.def_map.borrow().get(&callee.id).unwrap();
|
||||
@ -295,7 +294,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
.map(|expr| const_expr_to_pat(tcx, &**expr,
|
||||
pat_id, span))
|
||||
.collect());
|
||||
PatKind::TupleStruct(path, Some(pats))
|
||||
PatKind::TupleStruct(path, pats, None)
|
||||
}
|
||||
|
||||
hir::ExprStruct(ref path, ref fields, None) => {
|
||||
|
@ -757,6 +757,7 @@ fn get_source(input: &Input, sess: &Session) -> (Vec<u8>, String) {
|
||||
let src_name = driver::source_name(input);
|
||||
let src = sess.codemap()
|
||||
.get_filemap(&src_name)
|
||||
.unwrap()
|
||||
.src
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
|
@ -251,7 +251,7 @@ mod svh_visitor {
|
||||
ExprType(..) => SawExprType,
|
||||
ExprIf(..) => SawExprIf,
|
||||
ExprWhile(..) => SawExprWhile,
|
||||
ExprLoop(_, id) => SawExprLoop(id.map(|id| id.as_str())),
|
||||
ExprLoop(_, id) => SawExprLoop(id.map(|id| id.node.as_str())),
|
||||
ExprMatch(..) => SawExprMatch,
|
||||
ExprClosure(..) => SawExprClosure,
|
||||
ExprBlock(..) => SawExprBlock,
|
||||
|
@ -13,7 +13,7 @@ use hair::cx::Cx;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use rustc_const_eval as const_eval;
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::pat_util::{pat_is_resolved_const, pat_is_binding};
|
||||
use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const, pat_is_binding};
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::mir::repr::*;
|
||||
use rustc::hir::{self, PatKind};
|
||||
@ -148,17 +148,23 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Tup(ref subpatterns) => {
|
||||
let subpatterns =
|
||||
subpatterns.iter()
|
||||
.enumerate()
|
||||
.map(|(i, subpattern)| FieldPattern {
|
||||
field: Field::new(i),
|
||||
pattern: self.to_pattern(subpattern),
|
||||
})
|
||||
.collect();
|
||||
PatKind::Tuple(ref subpatterns, ddpos) => {
|
||||
match self.cx.tcx.node_id_to_type(pat.id).sty {
|
||||
ty::TyTuple(ref tys) => {
|
||||
let subpatterns =
|
||||
subpatterns.iter()
|
||||
.enumerate_and_adjust(tys.len(), ddpos)
|
||||
.map(|(i, subpattern)| FieldPattern {
|
||||
field: Field::new(i),
|
||||
pattern: self.to_pattern(subpattern),
|
||||
})
|
||||
.collect();
|
||||
|
||||
PatternKind::Leaf { subpatterns: subpatterns }
|
||||
PatternKind::Leaf { subpatterns: subpatterns }
|
||||
}
|
||||
|
||||
ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty),
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Ident(bm, ref ident, ref sub)
|
||||
@ -208,11 +214,18 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
self.variant_or_leaf(pat, vec![])
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(_, ref opt_subpatterns) => {
|
||||
PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
|
||||
let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
|
||||
let adt_def = match pat_ty.sty {
|
||||
ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def,
|
||||
_ => span_bug!(pat.span, "tuple struct pattern not applied to struct or enum"),
|
||||
};
|
||||
let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
|
||||
let variant_def = adt_def.variant_of_def(def);
|
||||
|
||||
let subpatterns =
|
||||
opt_subpatterns.iter()
|
||||
.flat_map(|v| v.iter())
|
||||
.enumerate()
|
||||
subpatterns.iter()
|
||||
.enumerate_and_adjust(variant_def.fields.len(), ddpos)
|
||||
.map(|(i, field)| FieldPattern {
|
||||
field: Field::new(i),
|
||||
pattern: self.to_pattern(field),
|
||||
|
@ -31,7 +31,7 @@ use std::mem::replace;
|
||||
|
||||
use rustc::hir::{self, PatKind};
|
||||
use rustc::hir::intravisit::{self, Visitor};
|
||||
|
||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::lint;
|
||||
use rustc::hir::def::{self, Def};
|
||||
@ -488,13 +488,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
self.check_field(pattern.span, adt, variant.field_named(field.node.name));
|
||||
}
|
||||
}
|
||||
|
||||
// Patterns which bind no fields are allowable (the path is check
|
||||
// elsewhere).
|
||||
PatKind::TupleStruct(_, Some(ref fields)) => {
|
||||
PatKind::TupleStruct(_, ref fields, ddpos) => {
|
||||
match self.tcx.pat_ty(pattern).sty {
|
||||
ty::TyStruct(def, _) => {
|
||||
for (i, field) in fields.iter().enumerate() {
|
||||
let expected_len = def.struct_variant().fields.len();
|
||||
for (i, field) in fields.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
if let PatKind::Wild = field.node {
|
||||
continue
|
||||
}
|
||||
@ -506,7 +504,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ use syntax::codemap::{Span, DUMMY_SP};
|
||||
use syntax::ast::{Block, Crate, DeclKind};
|
||||
use syntax::ast::{ForeignItem, ForeignItemKind, Item, ItemKind};
|
||||
use syntax::ast::{Mutability, PathListItemKind};
|
||||
use syntax::ast::{SelfKind, Stmt, StmtKind, TraitItemKind};
|
||||
use syntax::ast::{Stmt, StmtKind, TraitItemKind};
|
||||
use syntax::ast::{Variant, ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||
use syntax::visit::{self, Visitor};
|
||||
|
||||
@ -335,7 +335,7 @@ impl<'b> Resolver<'b> {
|
||||
let (def, ns) = match item.node {
|
||||
TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS),
|
||||
TraitItemKind::Method(ref sig, _) => {
|
||||
is_static_method = sig.explicit_self.node == SelfKind::Static;
|
||||
is_static_method = !sig.decl.has_self();
|
||||
(Def::Method(item_def_id), ValueNS)
|
||||
}
|
||||
TraitItemKind::Type(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
|
||||
|
@ -67,7 +67,7 @@ use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
|
||||
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
|
||||
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
||||
use syntax::ast::{Local, Pat, PatKind, Path};
|
||||
use syntax::ast::{PathSegment, PathParameters, SelfKind, TraitItemKind, TraitRef, Ty, TyKind};
|
||||
use syntax::ast::{PathSegment, PathParameters, TraitItemKind, TraitRef, Ty, TyKind};
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::cell::{Cell, RefCell};
|
||||
@ -607,7 +607,7 @@ impl<'a, 'v> Visitor<'v> for Resolver<'a> {
|
||||
}
|
||||
FnKind::Method(_, sig, _) => {
|
||||
self.visit_generics(&sig.generics);
|
||||
MethodRibKind(sig.explicit_self.node == SelfKind::Static)
|
||||
MethodRibKind(!sig.decl.has_self())
|
||||
}
|
||||
FnKind::Closure => ClosureRibKind(node_id),
|
||||
};
|
||||
@ -1676,9 +1676,7 @@ impl<'a> Resolver<'a> {
|
||||
let type_parameters =
|
||||
HasTypeParameters(&sig.generics,
|
||||
FnSpace,
|
||||
MethodRibKind(
|
||||
sig.explicit_self.node ==
|
||||
SelfKind::Static));
|
||||
MethodRibKind(!sig.decl.has_self()));
|
||||
this.with_type_parameter_rib(type_parameters, |this| {
|
||||
visit::walk_trait_item(this, trait_item)
|
||||
});
|
||||
@ -2007,9 +2005,7 @@ impl<'a> Resolver<'a> {
|
||||
let type_parameters =
|
||||
HasTypeParameters(&sig.generics,
|
||||
FnSpace,
|
||||
MethodRibKind(
|
||||
sig.explicit_self.node ==
|
||||
SelfKind::Static));
|
||||
MethodRibKind(!sig.decl.has_self()));
|
||||
this.with_type_parameter_rib(type_parameters, |this| {
|
||||
visit::walk_impl_item(this, impl_item);
|
||||
});
|
||||
@ -2360,7 +2356,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(ref path, _) | PatKind::Path(ref path) => {
|
||||
PatKind::TupleStruct(ref path, _, _) | PatKind::Path(ref path) => {
|
||||
// This must be an enum variant, struct or const.
|
||||
let resolution = match self.resolve_possibly_assoc_item(pat_id,
|
||||
None,
|
||||
@ -3128,7 +3124,7 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
{
|
||||
let rib = this.label_ribs.last_mut().unwrap();
|
||||
rib.bindings.insert(mtwt::resolve(label), def);
|
||||
rib.bindings.insert(mtwt::resolve(label.node), def);
|
||||
}
|
||||
|
||||
visit::walk_expr(this, expr);
|
||||
@ -3173,7 +3169,7 @@ impl<'a> Resolver<'a> {
|
||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
||||
self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new());
|
||||
|
||||
self.resolve_labeled_block(label, expr.id, block);
|
||||
self.resolve_labeled_block(label.map(|l| l.node), expr.id, block);
|
||||
|
||||
self.value_ribs.pop();
|
||||
}
|
||||
@ -3183,7 +3179,7 @@ impl<'a> Resolver<'a> {
|
||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
||||
self.resolve_pattern(pattern, LocalIrrefutableMode, &mut HashMap::new());
|
||||
|
||||
self.resolve_labeled_block(label, expr.id, block);
|
||||
self.resolve_labeled_block(label.map(|l| l.node), expr.id, block);
|
||||
|
||||
self.value_ribs.pop();
|
||||
}
|
||||
|
@ -696,7 +696,7 @@ impl<'v> Visitor<'v> for PathCollector {
|
||||
self.collected_paths.push((p.id, path.clone(),
|
||||
ast::Mutability::Mutable, recorder::TypeRef));
|
||||
}
|
||||
PatKind::TupleStruct(ref path, _) |
|
||||
PatKind::TupleStruct(ref path, _, _) |
|
||||
PatKind::Path(ref path) |
|
||||
PatKind::QPath(_, ref path) => {
|
||||
self.collected_paths.push((p.id, path.clone(),
|
||||
|
@ -792,7 +792,7 @@ fn any_irrefutable_adt_pat(tcx: TyCtxt, m: &[Match], col: usize) -> bool {
|
||||
m.iter().any(|br| {
|
||||
let pat = br.pats[col];
|
||||
match pat.node {
|
||||
PatKind::Tup(_) => true,
|
||||
PatKind::Tuple(..) => true,
|
||||
PatKind::Struct(..) | PatKind::TupleStruct(..) |
|
||||
PatKind::Path(..) | PatKind::Ident(_, _, None) => {
|
||||
match tcx.def_map.borrow().get(&pat.id).unwrap().full_def() {
|
||||
@ -1833,7 +1833,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
bcx = bind_irrefutable_pat(bcx, &inner_pat, val, cleanup_scope);
|
||||
}
|
||||
}
|
||||
PatKind::TupleStruct(_, ref sub_pats) => {
|
||||
PatKind::TupleStruct(_, ref sub_pats, ddpos) => {
|
||||
let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
|
||||
match opt_def {
|
||||
Some(Def::Variant(enum_id, var_id)) => {
|
||||
@ -1843,35 +1843,34 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
&repr,
|
||||
Disr::from(vinfo.disr_val),
|
||||
val);
|
||||
if let Some(ref sub_pat) = *sub_pats {
|
||||
for (i, &argval) in args.vals.iter().enumerate() {
|
||||
bcx = bind_irrefutable_pat(
|
||||
bcx,
|
||||
&sub_pat[i],
|
||||
MatchInput::from_val(argval),
|
||||
cleanup_scope);
|
||||
}
|
||||
for (i, subpat) in sub_pats.iter()
|
||||
.enumerate_and_adjust(vinfo.fields.len(), ddpos) {
|
||||
bcx = bind_irrefutable_pat(
|
||||
bcx,
|
||||
subpat,
|
||||
MatchInput::from_val(args.vals[i]),
|
||||
cleanup_scope);
|
||||
}
|
||||
}
|
||||
Some(Def::Struct(..)) => {
|
||||
match *sub_pats {
|
||||
None => {
|
||||
// This is a unit-like struct. Nothing to do here.
|
||||
let expected_len = match *ccx.tcx().pat_ty(&pat) {
|
||||
ty::TyS{sty: ty::TyStruct(adt_def, _), ..} => {
|
||||
adt_def.struct_variant().fields.len()
|
||||
}
|
||||
Some(ref elems) => {
|
||||
// This is the tuple struct case.
|
||||
let repr = adt::represent_node(bcx, pat.id);
|
||||
let val = adt::MaybeSizedValue::sized(val.val);
|
||||
for (i, elem) in elems.iter().enumerate() {
|
||||
let fldptr = adt::trans_field_ptr(bcx, &repr,
|
||||
val, Disr(0), i);
|
||||
bcx = bind_irrefutable_pat(
|
||||
bcx,
|
||||
&elem,
|
||||
MatchInput::from_val(fldptr),
|
||||
cleanup_scope);
|
||||
}
|
||||
ref ty => {
|
||||
span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
|
||||
}
|
||||
};
|
||||
|
||||
let repr = adt::represent_node(bcx, pat.id);
|
||||
let val = adt::MaybeSizedValue::sized(val.val);
|
||||
for (i, elem) in sub_pats.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
let fldptr = adt::trans_field_ptr(bcx, &repr, val, Disr(0), i);
|
||||
bcx = bind_irrefutable_pat(
|
||||
bcx,
|
||||
&elem,
|
||||
MatchInput::from_val(fldptr),
|
||||
cleanup_scope);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -1919,16 +1918,21 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
cleanup_scope);
|
||||
}
|
||||
}
|
||||
PatKind::Tup(ref elems) => {
|
||||
let repr = adt::represent_node(bcx, pat.id);
|
||||
let val = adt::MaybeSizedValue::sized(val.val);
|
||||
for (i, elem) in elems.iter().enumerate() {
|
||||
let fldptr = adt::trans_field_ptr(bcx, &repr, val, Disr(0), i);
|
||||
bcx = bind_irrefutable_pat(
|
||||
bcx,
|
||||
&elem,
|
||||
MatchInput::from_val(fldptr),
|
||||
cleanup_scope);
|
||||
PatKind::Tuple(ref elems, ddpos) => {
|
||||
match tcx.node_id_to_type(pat.id).sty {
|
||||
ty::TyTuple(ref tys) => {
|
||||
let repr = adt::represent_node(bcx, pat.id);
|
||||
let val = adt::MaybeSizedValue::sized(val.val);
|
||||
for (i, elem) in elems.iter().enumerate_and_adjust(tys.len(), ddpos) {
|
||||
let fldptr = adt::trans_field_ptr(bcx, &repr, val, Disr(0), i);
|
||||
bcx = bind_irrefutable_pat(
|
||||
bcx,
|
||||
&elem,
|
||||
MatchInput::from_val(fldptr),
|
||||
cleanup_scope);
|
||||
}
|
||||
}
|
||||
ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty),
|
||||
}
|
||||
}
|
||||
PatKind::Box(ref inner) => {
|
||||
|
@ -318,13 +318,11 @@ fn walk_pattern(cx: &CrateContext,
|
||||
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(_, ref sub_pats_opt) => {
|
||||
PatKind::TupleStruct(_, ref sub_pats, _) => {
|
||||
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
||||
|
||||
if let Some(ref sub_pats) = *sub_pats_opt {
|
||||
for p in sub_pats {
|
||||
walk_pattern(cx, &p, scope_stack, scope_map);
|
||||
}
|
||||
for p in sub_pats {
|
||||
walk_pattern(cx, &p, scope_stack, scope_map);
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,7 +341,7 @@ fn walk_pattern(cx: &CrateContext,
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Tup(ref sub_pats) => {
|
||||
PatKind::Tuple(ref sub_pats, _) => {
|
||||
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
||||
|
||||
for sub_pat in sub_pats {
|
||||
|
@ -1833,8 +1833,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
// lifetime elision, we can determine it in two ways. First (determined
|
||||
// here), if self is by-reference, then the implied output region is the
|
||||
// region of the self parameter.
|
||||
let explicit_self = decl.inputs.get(0).and_then(hir::Arg::to_self);
|
||||
let (self_ty, explicit_self_category) = match (opt_untransformed_self_ty, explicit_self) {
|
||||
let (self_ty, explicit_self_category) = match (opt_untransformed_self_ty, decl.get_self()) {
|
||||
(Some(untransformed_self_ty), Some(explicit_self)) => {
|
||||
let self_type = self.determine_self_type(&rb, untransformed_self_ty,
|
||||
&explicit_self);
|
||||
|
@ -11,7 +11,7 @@
|
||||
use hir::def::{self, Def};
|
||||
use rustc::infer::{self, InferOk, TypeOrigin};
|
||||
use hir::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
|
||||
use hir::pat_util::pat_is_resolved_const;
|
||||
use hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
|
||||
use check::{FnCtxt, Expectation};
|
||||
@ -213,13 +213,13 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
PatKind::Ident(_, ref path, _) => {
|
||||
let path = hir::Path::from_name(path.span, path.node);
|
||||
self.check_pat_enum(pat, &path, Some(&[]), expected, false);
|
||||
self.check_pat_enum(pat, &path, &[], None, expected, false);
|
||||
}
|
||||
PatKind::TupleStruct(ref path, ref subpats) => {
|
||||
self.check_pat_enum(pat, path, subpats.as_ref().map(|v| &v[..]), expected, true);
|
||||
PatKind::TupleStruct(ref path, ref subpats, ddpos) => {
|
||||
self.check_pat_enum(pat, path, &subpats, ddpos, expected, true);
|
||||
}
|
||||
PatKind::Path(ref path) => {
|
||||
self.check_pat_enum(pat, path, Some(&[]), expected, false);
|
||||
self.check_pat_enum(pat, path, &[], None, expected, false);
|
||||
}
|
||||
PatKind::QPath(ref qself, ref path) => {
|
||||
let self_ty = self.to_ty(&qself.ty);
|
||||
@ -260,14 +260,23 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
PatKind::Struct(ref path, ref fields, etc) => {
|
||||
self.check_pat_struct(pat, path, fields, etc, expected);
|
||||
}
|
||||
PatKind::Tup(ref elements) => {
|
||||
let element_tys: Vec<_> =
|
||||
(0..elements.len()).map(|_| self.next_ty_var()).collect();
|
||||
PatKind::Tuple(ref elements, ddpos) => {
|
||||
let mut expected_len = elements.len();
|
||||
if ddpos.is_some() {
|
||||
// Require known type only when `..` is present
|
||||
if let ty::TyTuple(ref tys) =
|
||||
self.structurally_resolved_type(pat.span, expected).sty {
|
||||
expected_len = tys.len();
|
||||
}
|
||||
}
|
||||
let max_len = cmp::max(expected_len, elements.len());
|
||||
|
||||
let element_tys: Vec<_> = (0 .. max_len).map(|_| self.next_ty_var()).collect();
|
||||
let pat_ty = tcx.mk_tup(element_tys.clone());
|
||||
self.write_ty(pat.id, pat_ty);
|
||||
self.demand_eqtype(pat.span, expected, pat_ty);
|
||||
for (element_pat, element_ty) in elements.iter().zip(element_tys) {
|
||||
self.check_pat(&element_pat, element_ty);
|
||||
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
|
||||
self.check_pat(elem, &element_tys[i]);
|
||||
}
|
||||
}
|
||||
PatKind::Box(ref inner) => {
|
||||
@ -615,7 +624,8 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
fn check_pat_enum(&self,
|
||||
pat: &hir::Pat,
|
||||
path: &hir::Path,
|
||||
subpats: Option<&'gcx [P<hir::Pat>]>,
|
||||
subpats: &'gcx [P<hir::Pat>],
|
||||
ddpos: Option<usize>,
|
||||
expected: Ty<'tcx>,
|
||||
is_tuple_struct_pat: bool)
|
||||
{
|
||||
@ -628,12 +638,9 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
self.set_tainted_by_errors();
|
||||
self.write_error(pat.id);
|
||||
|
||||
if let Some(subpats) = subpats {
|
||||
for pat in subpats {
|
||||
self.check_pat(&pat, tcx.types.err);
|
||||
}
|
||||
for pat in subpats {
|
||||
self.check_pat(&pat, tcx.types.err);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
@ -670,15 +677,12 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
self.instantiate_path(segments, path_scheme, &ctor_predicates,
|
||||
opt_ty, def, pat.span, pat.id);
|
||||
|
||||
let report_bad_struct_kind = |is_warning| {
|
||||
bad_struct_kind_err(tcx.sess, pat, path, is_warning);
|
||||
if is_warning { return; }
|
||||
self.write_error(pat.id);
|
||||
if let Some(subpats) = subpats {
|
||||
for pat in subpats {
|
||||
self.check_pat(&pat, tcx.types.err);
|
||||
}
|
||||
for pat in subpats {
|
||||
self.check_pat(&pat, tcx.types.err);
|
||||
}
|
||||
};
|
||||
|
||||
@ -715,11 +719,13 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
match (is_tuple_struct_pat, variant.kind()) {
|
||||
(true, ty::VariantKind::Unit) => {
|
||||
(true, ty::VariantKind::Unit) if subpats.is_empty() && ddpos.is_some() => {
|
||||
// Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
|
||||
// is allowed for backward compatibility.
|
||||
report_bad_struct_kind(true);
|
||||
}
|
||||
(true, ty::VariantKind::Unit) |
|
||||
(false, ty::VariantKind::Tuple) |
|
||||
(_, ty::VariantKind::Struct) => {
|
||||
report_bad_struct_kind(false);
|
||||
return
|
||||
@ -727,30 +733,21 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let Some(subpats) = subpats {
|
||||
if subpats.len() == variant.fields.len() {
|
||||
for (subpat, field) in subpats.iter().zip(&variant.fields) {
|
||||
let field_ty = self.field_ty(subpat.span, field, expected_substs);
|
||||
self.check_pat(&subpat, field_ty);
|
||||
}
|
||||
} else if variant.fields.is_empty() {
|
||||
span_err!(tcx.sess, pat.span, E0024,
|
||||
"this pattern has {} field{}, but the corresponding {} has no fields",
|
||||
subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name);
|
||||
if subpats.len() == variant.fields.len() ||
|
||||
subpats.len() < variant.fields.len() && ddpos.is_some() {
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
|
||||
let field_ty = self.field_ty(subpat.span, &variant.fields[i], expected_substs);
|
||||
self.check_pat(&subpat, field_ty);
|
||||
}
|
||||
} else {
|
||||
span_err!(tcx.sess, pat.span, E0023,
|
||||
"this pattern has {} field{}, but the corresponding {} has {} field{}",
|
||||
subpats.len(), if subpats.len() == 1 {""} else {"s"},
|
||||
kind_name,
|
||||
variant.fields.len(), if variant.fields.len() == 1 {""} else {"s"});
|
||||
|
||||
for pat in subpats {
|
||||
self.check_pat(&pat, tcx.types.err);
|
||||
}
|
||||
} else {
|
||||
span_err!(tcx.sess, pat.span, E0023,
|
||||
"this pattern has {} field{}, but the corresponding {} has {} field{}",
|
||||
subpats.len(), if subpats.len() == 1 {""} else {"s"},
|
||||
kind_name,
|
||||
variant.fields.len(), if variant.fields.len() == 1 {""} else {"s"});
|
||||
|
||||
for pat in subpats {
|
||||
self.check_pat(&pat, tcx.types.err);
|
||||
}
|
||||
for pat in subpats {
|
||||
self.check_pat(&pat, tcx.types.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,31 +62,6 @@ Check how many fields the enum was declared with and ensure that your pattern
|
||||
uses the same number.
|
||||
"##,
|
||||
|
||||
E0024: r##"
|
||||
This error indicates that a pattern attempted to extract the fields of an enum
|
||||
variant with no fields. Here's a tiny example of this error:
|
||||
|
||||
```compile_fail
|
||||
// This enum has two variants.
|
||||
enum Number {
|
||||
// This variant has no fields.
|
||||
Zero,
|
||||
// This variant has one field.
|
||||
One(u32)
|
||||
}
|
||||
|
||||
// Assuming x is a Number we can pattern match on its contents.
|
||||
match x {
|
||||
Number::Zero(inside) => {},
|
||||
Number::One(inside) => {},
|
||||
}
|
||||
```
|
||||
|
||||
The pattern match `Zero(inside)` is incorrect because the `Zero` variant
|
||||
contains no fields, yet the `inside` name attempts to bind the first field of
|
||||
the enum.
|
||||
"##,
|
||||
|
||||
E0025: r##"
|
||||
Each field of a struct can only be bound once in a pattern. Erroneous code
|
||||
example:
|
||||
|
@ -2579,7 +2579,7 @@ fn name_from_pat(p: &hir::Pat) -> String {
|
||||
match p.node {
|
||||
PatKind::Wild => "_".to_string(),
|
||||
PatKind::Ident(_, ref p, _) => p.node.to_string(),
|
||||
PatKind::TupleStruct(ref p, _) | PatKind::Path(ref p) => path_to_string(p),
|
||||
PatKind::TupleStruct(ref p, _, _) | PatKind::Path(ref p) => path_to_string(p),
|
||||
PatKind::QPath(..) => panic!("tried to get argument name from PatKind::QPath, \
|
||||
which is not allowed in function arguments"),
|
||||
PatKind::Struct(ref name, ref fields, etc) => {
|
||||
@ -2590,7 +2590,7 @@ fn name_from_pat(p: &hir::Pat) -> String {
|
||||
if etc { ", ..." } else { "" }
|
||||
)
|
||||
},
|
||||
PatKind::Tup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
|
||||
PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
|
||||
.collect::<Vec<String>>().join(", ")),
|
||||
PatKind::Box(ref p) => name_from_pat(&**p),
|
||||
PatKind::Ref(ref p, _) => name_from_pat(&**p),
|
||||
|
@ -567,7 +567,7 @@ impl Pat {
|
||||
PatKind::Struct(_, ref fields, _) => {
|
||||
fields.iter().all(|field| field.node.pat.walk(it))
|
||||
}
|
||||
PatKind::TupleStruct(_, Some(ref s)) | PatKind::Tup(ref s) => {
|
||||
PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
|
||||
s.iter().all(|p| p.walk(it))
|
||||
}
|
||||
PatKind::Box(ref s) | PatKind::Ref(ref s, _) => {
|
||||
@ -582,7 +582,6 @@ impl Pat {
|
||||
PatKind::Lit(_) |
|
||||
PatKind::Range(_, _) |
|
||||
PatKind::Ident(_, _, _) |
|
||||
PatKind::TupleStruct(..) |
|
||||
PatKind::Path(..) |
|
||||
PatKind::QPath(_, _) |
|
||||
PatKind::Mac(_) => {
|
||||
@ -631,9 +630,10 @@ pub enum PatKind {
|
||||
/// The `bool` is `true` in the presence of a `..`.
|
||||
Struct(Path, Vec<Spanned<FieldPat>>, bool),
|
||||
|
||||
/// A tuple struct/variant pattern `Variant(x, y, z)`.
|
||||
/// "None" means a `Variant(..)` pattern where we don't bind the fields to names.
|
||||
TupleStruct(Path, Option<Vec<P<Pat>>>),
|
||||
/// A tuple struct/variant pattern `Variant(x, y, .., z)`.
|
||||
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
|
||||
/// 0 <= position <= subpats.len()
|
||||
TupleStruct(Path, Vec<P<Pat>>, Option<usize>),
|
||||
|
||||
/// A path pattern.
|
||||
/// Such pattern can be resolved to a unit struct/variant or a constant.
|
||||
@ -645,8 +645,10 @@ pub enum PatKind {
|
||||
/// PatKind::Path, and the resolver will have to sort that out.
|
||||
QPath(QSelf, Path),
|
||||
|
||||
/// A tuple pattern `(a, b)`
|
||||
Tup(Vec<P<Pat>>),
|
||||
/// A tuple pattern `(a, b)`.
|
||||
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
|
||||
/// 0 <= position <= subpats.len()
|
||||
Tuple(Vec<P<Pat>>, Option<usize>),
|
||||
/// A `box` pattern
|
||||
Box(P<Pat>),
|
||||
/// A reference pattern, e.g. `&mut (a, b)`
|
||||
@ -1007,23 +1009,23 @@ pub enum ExprKind {
|
||||
/// A while loop, with an optional label
|
||||
///
|
||||
/// `'label: while expr { block }`
|
||||
While(P<Expr>, P<Block>, Option<Ident>),
|
||||
While(P<Expr>, P<Block>, Option<SpannedIdent>),
|
||||
/// A while-let loop, with an optional label
|
||||
///
|
||||
/// `'label: while let pat = expr { block }`
|
||||
///
|
||||
/// This is desugared to a combination of `loop` and `match` expressions.
|
||||
WhileLet(P<Pat>, P<Expr>, P<Block>, Option<Ident>),
|
||||
WhileLet(P<Pat>, P<Expr>, P<Block>, Option<SpannedIdent>),
|
||||
/// A for loop, with an optional label
|
||||
///
|
||||
/// `'label: for pat in expr { block }`
|
||||
///
|
||||
/// This is desugared to a combination of `loop` and `match` expressions.
|
||||
ForLoop(P<Pat>, P<Expr>, P<Block>, Option<Ident>),
|
||||
ForLoop(P<Pat>, P<Expr>, P<Block>, Option<SpannedIdent>),
|
||||
/// Conditionless loop (can be exited with break, continue, or return)
|
||||
///
|
||||
/// `'label: loop { block }`
|
||||
Loop(P<Block>, Option<Ident>),
|
||||
Loop(P<Block>, Option<SpannedIdent>),
|
||||
/// A `match` block.
|
||||
Match(P<Expr>, Vec<Arm>),
|
||||
/// A closure (for example, `move |a, b, c| {a + b + c}`)
|
||||
@ -1387,7 +1389,6 @@ pub struct MethodSig {
|
||||
pub abi: Abi,
|
||||
pub decl: P<FnDecl>,
|
||||
pub generics: Generics,
|
||||
pub explicit_self: ExplicitSelf,
|
||||
}
|
||||
|
||||
/// Represents an item declaration within a trait declaration,
|
||||
@ -1638,6 +1639,8 @@ pub enum TyKind {
|
||||
/// TyKind::Infer means the type should be inferred instead of it having been
|
||||
/// specified. This can appear anywhere in a type.
|
||||
Infer,
|
||||
/// Inferred type of a `self` or `&self` argument in a method.
|
||||
ImplicitSelf,
|
||||
// A macro in the type position.
|
||||
Mac(Mac),
|
||||
}
|
||||
@ -1677,81 +1680,65 @@ pub struct Arg {
|
||||
pub id: NodeId,
|
||||
}
|
||||
|
||||
/// Represents the kind of 'self' associated with a method.
|
||||
/// String representation of `Ident` here is always "self", but hygiene contexts may differ.
|
||||
/// Alternative representation for `Arg`s describing `self` parameter of methods.
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum SelfKind {
|
||||
/// No self
|
||||
Static,
|
||||
/// `self`, `mut self`
|
||||
Value(Ident),
|
||||
Value(Mutability),
|
||||
/// `&'lt self`, `&'lt mut self`
|
||||
Region(Option<Lifetime>, Mutability, Ident),
|
||||
Region(Option<Lifetime>, Mutability),
|
||||
/// `self: TYPE`, `mut self: TYPE`
|
||||
Explicit(P<Ty>, Ident),
|
||||
Explicit(P<Ty>, Mutability),
|
||||
}
|
||||
|
||||
pub type ExplicitSelf = Spanned<SelfKind>;
|
||||
|
||||
impl Arg {
|
||||
#[unstable(feature = "rustc_private", issue = "27812")]
|
||||
#[rustc_deprecated(since = "1.10.0", reason = "use `from_self` instead")]
|
||||
pub fn new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg {
|
||||
let path = Spanned{span:span,node:self_ident};
|
||||
Arg {
|
||||
// HACK(eddyb) fake type for the self argument.
|
||||
ty: P(Ty {
|
||||
id: DUMMY_NODE_ID,
|
||||
node: TyKind::Infer,
|
||||
span: DUMMY_SP,
|
||||
}),
|
||||
pat: P(Pat {
|
||||
id: DUMMY_NODE_ID,
|
||||
node: PatKind::Ident(BindingMode::ByValue(mutability), path, None),
|
||||
span: span
|
||||
}),
|
||||
id: DUMMY_NODE_ID
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_self(&self) -> Option<ExplicitSelf> {
|
||||
if let PatKind::Ident(_, ident, _) = self.pat.node {
|
||||
if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node {
|
||||
if ident.node.name == keywords::SelfValue.name() {
|
||||
return match self.ty.node {
|
||||
TyKind::Infer => Some(respan(self.pat.span, SelfKind::Value(ident.node))),
|
||||
TyKind::Rptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyKind::Infer => {
|
||||
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl, ident.node)))
|
||||
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
|
||||
TyKind::Rptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyKind::ImplicitSelf => {
|
||||
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
|
||||
}
|
||||
_ => Some(respan(mk_sp(self.pat.span.lo, self.ty.span.hi),
|
||||
SelfKind::Explicit(self.ty.clone(), ident.node))),
|
||||
SelfKind::Explicit(self.ty.clone(), mutbl))),
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn from_self(eself: ExplicitSelf, ident_sp: Span, mutbl: Mutability) -> Arg {
|
||||
let pat = |ident, span| P(Pat {
|
||||
id: DUMMY_NODE_ID,
|
||||
node: PatKind::Ident(BindingMode::ByValue(mutbl), respan(ident_sp, ident), None),
|
||||
span: span,
|
||||
});
|
||||
pub fn is_self(&self) -> bool {
|
||||
if let PatKind::Ident(_, ident, _) = self.pat.node {
|
||||
ident.node.name == keywords::SelfValue.name()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg {
|
||||
let infer_ty = P(Ty {
|
||||
id: DUMMY_NODE_ID,
|
||||
node: TyKind::Infer,
|
||||
node: TyKind::ImplicitSelf,
|
||||
span: DUMMY_SP,
|
||||
});
|
||||
let arg = |ident, ty, span| Arg {
|
||||
pat: pat(ident, span),
|
||||
let arg = |mutbl, ty, span| Arg {
|
||||
pat: P(Pat {
|
||||
id: DUMMY_NODE_ID,
|
||||
node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
|
||||
span: span,
|
||||
}),
|
||||
ty: ty,
|
||||
id: DUMMY_NODE_ID,
|
||||
};
|
||||
match eself.node {
|
||||
SelfKind::Static => panic!("bug: `Arg::from_self` is called \
|
||||
with `SelfKind::Static` argument"),
|
||||
SelfKind::Explicit(ty, ident) => arg(ident, ty, mk_sp(eself.span.lo, ident_sp.hi)),
|
||||
SelfKind::Value(ident) => arg(ident, infer_ty, eself.span),
|
||||
SelfKind::Region(lt, mutbl, ident) => arg(ident, P(Ty {
|
||||
SelfKind::Explicit(ty, mutbl) => {
|
||||
arg(mutbl, ty, mk_sp(eself.span.lo, eself_ident.span.hi))
|
||||
}
|
||||
SelfKind::Value(mutbl) => arg(mutbl, infer_ty, eself.span),
|
||||
SelfKind::Region(lt, mutbl) => arg(Mutability::Immutable, P(Ty {
|
||||
id: DUMMY_NODE_ID,
|
||||
node: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl: mutbl }),
|
||||
span: DUMMY_SP,
|
||||
@ -1768,6 +1755,15 @@ pub struct FnDecl {
|
||||
pub variadic: bool
|
||||
}
|
||||
|
||||
impl FnDecl {
|
||||
pub fn get_self(&self) -> Option<ExplicitSelf> {
|
||||
self.inputs.get(0).and_then(Arg::to_self)
|
||||
}
|
||||
pub fn has_self(&self) -> bool {
|
||||
self.inputs.get(0).map(Arg::is_self).unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum Unsafety {
|
||||
Unsafe,
|
||||
|
@ -1191,13 +1191,13 @@ impl CodeMap {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_filemap(&self, filename: &str) -> Rc<FileMap> {
|
||||
pub fn get_filemap(&self, filename: &str) -> Option<Rc<FileMap>> {
|
||||
for fm in self.files.borrow().iter() {
|
||||
if filename == fm.name {
|
||||
return fm.clone();
|
||||
return Some(fm.clone());
|
||||
}
|
||||
}
|
||||
panic!("asking for {} which we don't know about", filename);
|
||||
None
|
||||
}
|
||||
|
||||
/// For a global BytePos compute the local offset within the containing FileMap
|
||||
|
@ -832,7 +832,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
let pat = if subpats.is_empty() {
|
||||
PatKind::Path(path)
|
||||
} else {
|
||||
PatKind::TupleStruct(path, Some(subpats))
|
||||
PatKind::TupleStruct(path, subpats, None)
|
||||
};
|
||||
self.pat(span, pat)
|
||||
}
|
||||
@ -842,7 +842,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
self.pat(span, pat)
|
||||
}
|
||||
fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
|
||||
self.pat(span, PatKind::Tup(pats))
|
||||
self.pat(span, PatKind::Tuple(pats, None))
|
||||
}
|
||||
|
||||
fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use ast::{Block, Crate, DeclKind, PatKind};
|
||||
use ast::{Local, Ident, Mac_, Name};
|
||||
use ast::{Local, Ident, Mac_, Name, SpannedIdent};
|
||||
use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind};
|
||||
use ast::TokenTree;
|
||||
use ast;
|
||||
@ -334,12 +334,12 @@ fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attr
|
||||
/// body is in a block enclosed by loop head so the renaming of loop label
|
||||
/// must be propagated to the enclosed context.
|
||||
fn expand_loop_block(loop_block: P<Block>,
|
||||
opt_ident: Option<Ident>,
|
||||
fld: &mut MacroExpander) -> (P<Block>, Option<Ident>) {
|
||||
opt_ident: Option<SpannedIdent>,
|
||||
fld: &mut MacroExpander) -> (P<Block>, Option<SpannedIdent>) {
|
||||
match opt_ident {
|
||||
Some(label) => {
|
||||
let new_label = fresh_name(label);
|
||||
let rename = (label, new_label);
|
||||
let new_label = fresh_name(label.node);
|
||||
let rename = (label.node, new_label);
|
||||
|
||||
// The rename *must not* be added to the pending list of current
|
||||
// syntax context otherwise an unrelated `break` or `continue` in
|
||||
@ -347,7 +347,7 @@ fn expand_loop_block(loop_block: P<Block>,
|
||||
// and be renamed incorrectly.
|
||||
let mut rename_list = vec!(rename);
|
||||
let mut rename_fld = IdentRenamer{renames: &mut rename_list};
|
||||
let renamed_ident = rename_fld.fold_ident(label);
|
||||
let renamed_ident = rename_fld.fold_ident(label.node);
|
||||
|
||||
// The rename *must* be added to the enclosed syntax context for
|
||||
// `break` or `continue` to pick up because by definition they are
|
||||
@ -357,7 +357,7 @@ fn expand_loop_block(loop_block: P<Block>,
|
||||
let expanded_block = expand_block_elts(loop_block, fld);
|
||||
fld.cx.syntax_env.pop_frame();
|
||||
|
||||
(expanded_block, Some(renamed_ident))
|
||||
(expanded_block, Some(Spanned { node: renamed_ident, span: label.span }))
|
||||
}
|
||||
None => (fld.fold_block(loop_block), opt_ident)
|
||||
}
|
||||
@ -950,7 +950,6 @@ fn expand_and_rename_method(sig: ast::MethodSig, body: P<ast::Block>,
|
||||
(ast::MethodSig {
|
||||
generics: fld.fold_generics(sig.generics),
|
||||
abi: sig.abi,
|
||||
explicit_self: fld.fold_explicit_self(sig.explicit_self),
|
||||
unsafety: sig.unsafety,
|
||||
constness: sig.constness,
|
||||
decl: rewritten_fn_decl
|
||||
|
@ -274,7 +274,10 @@ declare_features! (
|
||||
(active, drop_types_in_const, "1.9.0", Some(33156)),
|
||||
|
||||
// Allows cfg(target_has_atomic = "...").
|
||||
(active, cfg_target_has_atomic, "1.9.0", Some(32976))
|
||||
(active, cfg_target_has_atomic, "1.9.0", Some(32976)),
|
||||
|
||||
// Allows `..` in tuple (struct) patterns
|
||||
(active, dotdot_in_tuple_patterns, "1.10.0", Some(33627))
|
||||
);
|
||||
|
||||
declare_features! (
|
||||
@ -315,7 +318,6 @@ declare_features! (
|
||||
// Allows `#[deprecated]` attribute
|
||||
(accepted, deprecated, "1.9.0", Some(29935))
|
||||
);
|
||||
|
||||
// (changing above list without updating src/doc/reference.md makes @cmr sad)
|
||||
|
||||
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||
@ -1024,6 +1026,24 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
|
||||
pattern.span,
|
||||
"box pattern syntax is experimental");
|
||||
}
|
||||
PatKind::Tuple(_, ddpos)
|
||||
if ddpos.is_some() => {
|
||||
gate_feature_post!(&self, dotdot_in_tuple_patterns,
|
||||
pattern.span,
|
||||
"`..` in tuple patterns is experimental");
|
||||
}
|
||||
PatKind::TupleStruct(_, ref fields, ddpos)
|
||||
if ddpos.is_some() && !fields.is_empty() => {
|
||||
gate_feature_post!(&self, dotdot_in_tuple_patterns,
|
||||
pattern.span,
|
||||
"`..` in tuple struct patterns is experimental");
|
||||
}
|
||||
PatKind::TupleStruct(_, ref fields, ddpos)
|
||||
if ddpos.is_none() && fields.is_empty() => {
|
||||
self.context.span_handler.struct_span_err(pattern.span,
|
||||
"nullary enum variants are written with \
|
||||
no trailing `( )`").emit();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_pat(self, pattern)
|
||||
|
@ -179,14 +179,6 @@ pub trait Folder : Sized {
|
||||
// fold::noop_fold_mac(_mac, self)
|
||||
}
|
||||
|
||||
fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf {
|
||||
noop_fold_explicit_self(es, self)
|
||||
}
|
||||
|
||||
fn fold_explicit_self_kind(&mut self, es: SelfKind) -> SelfKind {
|
||||
noop_fold_explicit_self_kind(es, self)
|
||||
}
|
||||
|
||||
fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
|
||||
noop_fold_lifetime(l, self)
|
||||
}
|
||||
@ -383,7 +375,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||
t.map(|Ty {id, node, span}| Ty {
|
||||
id: fld.new_id(id),
|
||||
node: match node {
|
||||
TyKind::Infer => node,
|
||||
TyKind::Infer | TyKind::ImplicitSelf => node,
|
||||
TyKind::Vec(ty) => TyKind::Vec(fld.fold_ty(ty)),
|
||||
TyKind::Ptr(mt) => TyKind::Ptr(fld.fold_mt(mt)),
|
||||
TyKind::Rptr(region, mt) => {
|
||||
@ -523,28 +515,6 @@ pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attr
|
||||
})
|
||||
}
|
||||
|
||||
pub fn noop_fold_explicit_self_kind<T: Folder>(es: SelfKind, fld: &mut T)
|
||||
-> SelfKind {
|
||||
match es {
|
||||
SelfKind::Static | SelfKind::Value(_) => es,
|
||||
SelfKind::Region(lifetime, m, ident) => {
|
||||
SelfKind::Region(fld.fold_opt_lifetime(lifetime), m, ident)
|
||||
}
|
||||
SelfKind::Explicit(typ, ident) => {
|
||||
SelfKind::Explicit(fld.fold_ty(typ), ident)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_explicit_self<T: Folder>(Spanned {span, node}: ExplicitSelf, fld: &mut T)
|
||||
-> ExplicitSelf {
|
||||
Spanned {
|
||||
node: fld.fold_explicit_self_kind(node),
|
||||
span: fld.new_span(span)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn noop_fold_mac<T: Folder>(Spanned {node, span}: Mac, fld: &mut T) -> Mac {
|
||||
Spanned {
|
||||
node: Mac_ {
|
||||
@ -1096,7 +1066,6 @@ pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> Method
|
||||
MethodSig {
|
||||
generics: folder.fold_generics(sig.generics),
|
||||
abi: sig.abi,
|
||||
explicit_self: folder.fold_explicit_self(sig.explicit_self),
|
||||
unsafety: sig.unsafety,
|
||||
constness: sig.constness,
|
||||
decl: folder.fold_fn_decl(sig.decl)
|
||||
@ -1115,9 +1084,9 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
|
||||
sub.map(|x| folder.fold_pat(x)))
|
||||
}
|
||||
PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)),
|
||||
PatKind::TupleStruct(pth, pats) => {
|
||||
PatKind::TupleStruct(pth, pats, ddpos) => {
|
||||
PatKind::TupleStruct(folder.fold_path(pth),
|
||||
pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
|
||||
pats.move_map(|x| folder.fold_pat(x)), ddpos)
|
||||
}
|
||||
PatKind::Path(pth) => {
|
||||
PatKind::Path(folder.fold_path(pth))
|
||||
@ -1138,7 +1107,9 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
|
||||
});
|
||||
PatKind::Struct(pth, fs, etc)
|
||||
}
|
||||
PatKind::Tup(elts) => PatKind::Tup(elts.move_map(|x| folder.fold_pat(x))),
|
||||
PatKind::Tuple(elts, ddpos) => {
|
||||
PatKind::Tuple(elts.move_map(|x| folder.fold_pat(x)), ddpos)
|
||||
}
|
||||
PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)),
|
||||
PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl),
|
||||
PatKind::Range(e1, e2) => {
|
||||
@ -1212,23 +1183,27 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
|
||||
ExprKind::While(cond, body, opt_ident) => {
|
||||
ExprKind::While(folder.fold_expr(cond),
|
||||
folder.fold_block(body),
|
||||
opt_ident.map(|i| folder.fold_ident(i)))
|
||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||
folder.fold_ident(label.node))))
|
||||
}
|
||||
ExprKind::WhileLet(pat, expr, body, opt_ident) => {
|
||||
ExprKind::WhileLet(folder.fold_pat(pat),
|
||||
folder.fold_expr(expr),
|
||||
folder.fold_block(body),
|
||||
opt_ident.map(|i| folder.fold_ident(i)))
|
||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||
folder.fold_ident(label.node))))
|
||||
}
|
||||
ExprKind::ForLoop(pat, iter, body, opt_ident) => {
|
||||
ExprKind::ForLoop(folder.fold_pat(pat),
|
||||
folder.fold_expr(iter),
|
||||
folder.fold_block(body),
|
||||
opt_ident.map(|i| folder.fold_ident(i)))
|
||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||
folder.fold_ident(label.node))))
|
||||
}
|
||||
ExprKind::Loop(body, opt_ident) => {
|
||||
ExprKind::Loop(folder.fold_block(body),
|
||||
opt_ident.map(|i| folder.fold_ident(i)))
|
||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||
folder.fold_ident(label.node))))
|
||||
}
|
||||
ExprKind::Match(expr, arms) => {
|
||||
ExprKind::Match(folder.fold_expr(expr),
|
||||
|
@ -17,7 +17,7 @@ use ast::Block;
|
||||
use ast::{BlockCheckMode, CaptureBy};
|
||||
use ast::{Constness, Crate, CrateConfig};
|
||||
use ast::{Decl, DeclKind, Defaultness};
|
||||
use ast::{EMPTY_CTXT, EnumDef, ExplicitSelf};
|
||||
use ast::{EMPTY_CTXT, EnumDef};
|
||||
use ast::{Expr, ExprKind, RangeLimits};
|
||||
use ast::{Field, FnDecl};
|
||||
use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
|
||||
@ -954,25 +954,6 @@ impl<'a> Parser<'a> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Parse a sequence parameter of enum variant. For consistency purposes,
|
||||
/// these should not be empty.
|
||||
pub fn parse_enum_variant_seq<T, F>(&mut self,
|
||||
bra: &token::Token,
|
||||
ket: &token::Token,
|
||||
sep: SeqSep,
|
||||
f: F)
|
||||
-> PResult<'a, Vec<T>> where
|
||||
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
{
|
||||
let result = self.parse_unspanned_seq(bra, ket, sep, f)?;
|
||||
if result.is_empty() {
|
||||
let last_span = self.last_span;
|
||||
self.span_err(last_span,
|
||||
"nullary enum variants are written with no trailing `( )`");
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// NB: Do not use this function unless you actually plan to place the
|
||||
// spanned list in the AST.
|
||||
pub fn parse_seq<T, F>(&mut self,
|
||||
@ -1310,7 +1291,7 @@ impl<'a> Parser<'a> {
|
||||
let ident = p.parse_ident()?;
|
||||
let mut generics = p.parse_generics()?;
|
||||
|
||||
let (explicit_self, d) = p.parse_fn_decl_with_self(|p: &mut Parser<'a>|{
|
||||
let d = p.parse_fn_decl_with_self(|p: &mut Parser<'a>|{
|
||||
// This is somewhat dubious; We don't want to allow
|
||||
// argument names to be left off if there is a
|
||||
// definition...
|
||||
@ -1324,7 +1305,6 @@ impl<'a> Parser<'a> {
|
||||
decl: d,
|
||||
generics: generics,
|
||||
abi: abi,
|
||||
explicit_self: explicit_self,
|
||||
};
|
||||
|
||||
let body = match p.token {
|
||||
@ -2283,18 +2263,19 @@ impl<'a> Parser<'a> {
|
||||
return self.parse_while_expr(None, lo, attrs);
|
||||
}
|
||||
if self.token.is_lifetime() {
|
||||
let lifetime = self.get_lifetime();
|
||||
let label = Spanned { node: self.get_lifetime(),
|
||||
span: self.span };
|
||||
let lo = self.span.lo;
|
||||
self.bump();
|
||||
self.expect(&token::Colon)?;
|
||||
if self.eat_keyword(keywords::While) {
|
||||
return self.parse_while_expr(Some(lifetime), lo, attrs)
|
||||
return self.parse_while_expr(Some(label), lo, attrs)
|
||||
}
|
||||
if self.eat_keyword(keywords::For) {
|
||||
return self.parse_for_expr(Some(lifetime), lo, attrs)
|
||||
return self.parse_for_expr(Some(label), lo, attrs)
|
||||
}
|
||||
if self.eat_keyword(keywords::Loop) {
|
||||
return self.parse_loop_expr(Some(lifetime), lo, attrs)
|
||||
return self.parse_loop_expr(Some(label), lo, attrs)
|
||||
}
|
||||
return Err(self.fatal("expected `while`, `for`, or `loop` after a label"))
|
||||
}
|
||||
@ -3264,7 +3245,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse a 'for' .. 'in' expression ('for' token already eaten)
|
||||
pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>,
|
||||
pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
||||
span_lo: BytePos,
|
||||
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
||||
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
|
||||
@ -3283,7 +3264,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse a 'while' or 'while let' expression ('while' token already eaten)
|
||||
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>,
|
||||
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
||||
span_lo: BytePos,
|
||||
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
||||
if self.token.is_keyword(keywords::Let) {
|
||||
@ -3298,7 +3279,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse a 'while let' expression ('while' token already eaten)
|
||||
pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>,
|
||||
pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
||||
span_lo: BytePos,
|
||||
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
||||
self.expect_keyword(keywords::Let)?;
|
||||
@ -3312,7 +3293,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
// parse `loop {...}`, `loop` token already eaten
|
||||
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>,
|
||||
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
||||
span_lo: BytePos,
|
||||
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
||||
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
@ -3433,21 +3414,33 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
}
|
||||
|
||||
fn parse_pat_tuple_elements(&mut self) -> PResult<'a, Vec<P<Pat>>> {
|
||||
fn parse_pat_tuple_elements(&mut self, unary_needs_comma: bool)
|
||||
-> PResult<'a, (Vec<P<Pat>>, Option<usize>)> {
|
||||
let mut fields = vec![];
|
||||
if !self.check(&token::CloseDelim(token::Paren)) {
|
||||
fields.push(self.parse_pat()?);
|
||||
if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) {
|
||||
while self.eat(&token::Comma) &&
|
||||
!self.check(&token::CloseDelim(token::Paren)) {
|
||||
let mut ddpos = None;
|
||||
|
||||
while !self.check(&token::CloseDelim(token::Paren)) {
|
||||
if ddpos.is_none() && self.eat(&token::DotDot) {
|
||||
ddpos = Some(fields.len());
|
||||
if self.eat(&token::Comma) {
|
||||
// `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
|
||||
fields.push(self.parse_pat()?);
|
||||
}
|
||||
} else if ddpos.is_some() && self.eat(&token::DotDot) {
|
||||
// Emit a friendly error, ignore `..` and continue parsing
|
||||
self.span_err(self.last_span, "`..` can only be used once per \
|
||||
tuple or tuple struct pattern");
|
||||
} else {
|
||||
fields.push(self.parse_pat()?);
|
||||
}
|
||||
if fields.len() == 1 {
|
||||
|
||||
if !self.check(&token::CloseDelim(token::Paren)) ||
|
||||
(unary_needs_comma && fields.len() == 1 && ddpos.is_none()) {
|
||||
self.expect(&token::Comma)?;
|
||||
}
|
||||
}
|
||||
Ok(fields)
|
||||
|
||||
Ok((fields, ddpos))
|
||||
}
|
||||
|
||||
fn parse_pat_vec_elements(
|
||||
@ -3626,9 +3619,9 @@ impl<'a> Parser<'a> {
|
||||
token::OpenDelim(token::Paren) => {
|
||||
// Parse (pat,pat,pat,...) as tuple pattern
|
||||
self.bump();
|
||||
let fields = self.parse_pat_tuple_elements()?;
|
||||
let (fields, ddpos) = self.parse_pat_tuple_elements(true)?;
|
||||
self.expect(&token::CloseDelim(token::Paren))?;
|
||||
pat = PatKind::Tup(fields);
|
||||
pat = PatKind::Tuple(fields, ddpos);
|
||||
}
|
||||
token::OpenDelim(token::Bracket) => {
|
||||
// Parse [pat,pat,...] as slice pattern
|
||||
@ -3713,20 +3706,10 @@ impl<'a> Parser<'a> {
|
||||
return Err(self.fatal("unexpected `(` after qualified path"));
|
||||
}
|
||||
// Parse tuple struct or enum pattern
|
||||
if self.look_ahead(1, |t| *t == token::DotDot) {
|
||||
// This is a "top constructor only" pat
|
||||
self.bump();
|
||||
self.bump();
|
||||
self.expect(&token::CloseDelim(token::Paren))?;
|
||||
pat = PatKind::TupleStruct(path, None);
|
||||
} else {
|
||||
let args = self.parse_enum_variant_seq(
|
||||
&token::OpenDelim(token::Paren),
|
||||
&token::CloseDelim(token::Paren),
|
||||
SeqSep::trailing_allowed(token::Comma),
|
||||
|p| p.parse_pat())?;
|
||||
pat = PatKind::TupleStruct(path, Some(args));
|
||||
}
|
||||
self.bump();
|
||||
let (fields, ddpos) = self.parse_pat_tuple_elements(false)?;
|
||||
self.expect(&token::CloseDelim(token::Paren))?;
|
||||
pat = PatKind::TupleStruct(path, fields, ddpos)
|
||||
}
|
||||
_ => {
|
||||
pat = match qself {
|
||||
@ -4616,25 +4599,19 @@ impl<'a> Parser<'a> {
|
||||
}))
|
||||
}
|
||||
|
||||
/// Parse the parameter list and result type of a function that may have a `self` parameter.
|
||||
fn parse_fn_decl_with_self<F>(&mut self,
|
||||
parse_arg_fn: F)
|
||||
-> PResult<'a, (ExplicitSelf, P<FnDecl>)>
|
||||
where F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>,
|
||||
{
|
||||
/// Returns the parsed optional self argument and whether a self shortcut was used.
|
||||
fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
|
||||
let expect_ident = |this: &mut Self| match this.token {
|
||||
token::Ident(ident) => { this.bump(); ident } // Preserve hygienic context.
|
||||
// Preserve hygienic context.
|
||||
token::Ident(ident) => { this.bump(); codemap::respan(this.last_span, ident) }
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
self.expect(&token::OpenDelim(token::Paren))?;
|
||||
|
||||
// Parse optional self parameter of a method.
|
||||
// Only a limited set of initial token sequences is considered self parameters, anything
|
||||
// else is parsed as a normal function parameter list, so some lookahead is required.
|
||||
let eself_lo = self.span.lo;
|
||||
let mut eself_mutbl = Mutability::Immutable;
|
||||
let (eself, eself_ident_sp) = match self.token {
|
||||
let (eself, eself_ident) = match self.token {
|
||||
token::BinOp(token::And) => {
|
||||
// &self
|
||||
// &mut self
|
||||
@ -4643,30 +4620,26 @@ impl<'a> Parser<'a> {
|
||||
// ¬_self
|
||||
if self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) {
|
||||
self.bump();
|
||||
(SelfKind::Region(None, Mutability::Immutable, expect_ident(self)),
|
||||
self.last_span)
|
||||
(SelfKind::Region(None, Mutability::Immutable), expect_ident(self))
|
||||
} else if self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) &&
|
||||
self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) {
|
||||
self.bump();
|
||||
self.bump();
|
||||
(SelfKind::Region(None, Mutability::Mutable, expect_ident(self)),
|
||||
self.last_span)
|
||||
(SelfKind::Region(None, Mutability::Mutable), expect_ident(self))
|
||||
} else if self.look_ahead(1, |t| t.is_lifetime()) &&
|
||||
self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) {
|
||||
self.bump();
|
||||
let lt = self.parse_lifetime()?;
|
||||
(SelfKind::Region(Some(lt), Mutability::Immutable, expect_ident(self)),
|
||||
self.last_span)
|
||||
(SelfKind::Region(Some(lt), Mutability::Immutable), expect_ident(self))
|
||||
} else if self.look_ahead(1, |t| t.is_lifetime()) &&
|
||||
self.look_ahead(2, |t| t.is_keyword(keywords::Mut)) &&
|
||||
self.look_ahead(3, |t| t.is_keyword(keywords::SelfValue)) {
|
||||
self.bump();
|
||||
let lt = self.parse_lifetime()?;
|
||||
self.bump();
|
||||
(SelfKind::Region(Some(lt), Mutability::Mutable, expect_ident(self)),
|
||||
self.last_span)
|
||||
(SelfKind::Region(Some(lt), Mutability::Mutable), expect_ident(self))
|
||||
} else {
|
||||
(SelfKind::Static, codemap::DUMMY_SP)
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
token::BinOp(token::Star) => {
|
||||
@ -4678,15 +4651,15 @@ impl<'a> Parser<'a> {
|
||||
if self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) {
|
||||
self.bump();
|
||||
self.span_err(self.span, "cannot pass `self` by raw pointer");
|
||||
(SelfKind::Value(expect_ident(self)), self.last_span)
|
||||
(SelfKind::Value(Mutability::Immutable), expect_ident(self))
|
||||
} else if self.look_ahead(1, |t| t.is_mutability()) &&
|
||||
self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) {
|
||||
self.bump();
|
||||
self.bump();
|
||||
self.span_err(self.span, "cannot pass `self` by raw pointer");
|
||||
(SelfKind::Value(expect_ident(self)), self.last_span)
|
||||
(SelfKind::Value(Mutability::Immutable), expect_ident(self))
|
||||
} else {
|
||||
(SelfKind::Static, codemap::DUMMY_SP)
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
token::Ident(..) => {
|
||||
@ -4694,64 +4667,69 @@ impl<'a> Parser<'a> {
|
||||
// self
|
||||
// self: TYPE
|
||||
let eself_ident = expect_ident(self);
|
||||
let eself_ident_sp = self.last_span;
|
||||
if self.eat(&token::Colon) {
|
||||
(SelfKind::Explicit(self.parse_ty_sum()?, eself_ident), eself_ident_sp)
|
||||
let ty = self.parse_ty_sum()?;
|
||||
(SelfKind::Explicit(ty, Mutability::Immutable), eself_ident)
|
||||
} else {
|
||||
(SelfKind::Value(eself_ident), eself_ident_sp)
|
||||
(SelfKind::Value(Mutability::Immutable), eself_ident)
|
||||
}
|
||||
} else if self.token.is_keyword(keywords::Mut) &&
|
||||
self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) {
|
||||
// mut self
|
||||
// mut self: TYPE
|
||||
eself_mutbl = Mutability::Mutable;
|
||||
self.bump();
|
||||
let eself_ident = expect_ident(self);
|
||||
let eself_ident_sp = self.last_span;
|
||||
if self.eat(&token::Colon) {
|
||||
(SelfKind::Explicit(self.parse_ty_sum()?, eself_ident), eself_ident_sp)
|
||||
let ty = self.parse_ty_sum()?;
|
||||
(SelfKind::Explicit(ty, Mutability::Mutable), eself_ident)
|
||||
} else {
|
||||
(SelfKind::Value(eself_ident), eself_ident_sp)
|
||||
(SelfKind::Value(Mutability::Mutable), eself_ident)
|
||||
}
|
||||
} else {
|
||||
(SelfKind::Static, codemap::DUMMY_SP)
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
_ => (SelfKind::Static, codemap::DUMMY_SP)
|
||||
_ => return Ok(None),
|
||||
};
|
||||
let mut eself = codemap::respan(mk_sp(eself_lo, self.last_span.hi), eself);
|
||||
|
||||
let eself = codemap::respan(mk_sp(eself_lo, self.last_span.hi), eself);
|
||||
Ok(Some(Arg::from_self(eself, eself_ident)))
|
||||
}
|
||||
|
||||
/// Parse the parameter list and result type of a function that may have a `self` parameter.
|
||||
fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDecl>>
|
||||
where F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>,
|
||||
{
|
||||
self.expect(&token::OpenDelim(token::Paren))?;
|
||||
|
||||
// Parse optional self argument
|
||||
let self_arg = self.parse_self_arg()?;
|
||||
|
||||
// Parse the rest of the function parameter list.
|
||||
let sep = SeqSep::trailing_allowed(token::Comma);
|
||||
let fn_inputs = match eself.node {
|
||||
SelfKind::Static => {
|
||||
eself.span = codemap::DUMMY_SP;
|
||||
self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)
|
||||
}
|
||||
SelfKind::Value(..) | SelfKind::Region(..) | SelfKind::Explicit(..) => {
|
||||
if self.check(&token::CloseDelim(token::Paren)) {
|
||||
vec![Arg::from_self(eself.clone(), eself_ident_sp, eself_mutbl)]
|
||||
} else if self.check(&token::Comma) {
|
||||
self.bump();
|
||||
let mut fn_inputs = vec![Arg::from_self(eself.clone(), eself_ident_sp,
|
||||
eself_mutbl)];
|
||||
fn_inputs.append(&mut self.parse_seq_to_before_end(
|
||||
&token::CloseDelim(token::Paren), sep, parse_arg_fn)
|
||||
);
|
||||
fn_inputs
|
||||
} else {
|
||||
return self.unexpected();
|
||||
}
|
||||
let fn_inputs = if let Some(self_arg) = self_arg {
|
||||
if self.check(&token::CloseDelim(token::Paren)) {
|
||||
vec![self_arg]
|
||||
} else if self.eat(&token::Comma) {
|
||||
let mut fn_inputs = vec![self_arg];
|
||||
fn_inputs.append(&mut self.parse_seq_to_before_end(
|
||||
&token::CloseDelim(token::Paren), sep, parse_arg_fn)
|
||||
);
|
||||
fn_inputs
|
||||
} else {
|
||||
return self.unexpected();
|
||||
}
|
||||
} else {
|
||||
self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)
|
||||
};
|
||||
|
||||
// Parse closing paren and return type.
|
||||
self.expect(&token::CloseDelim(token::Paren))?;
|
||||
Ok((eself, P(FnDecl {
|
||||
Ok(P(FnDecl {
|
||||
inputs: fn_inputs,
|
||||
output: self.parse_ret_ty()?,
|
||||
variadic: false
|
||||
})))
|
||||
}))
|
||||
}
|
||||
|
||||
// parse the |arg, arg| header on a lambda
|
||||
@ -4944,15 +4922,12 @@ impl<'a> Parser<'a> {
|
||||
let (constness, unsafety, abi) = self.parse_fn_front_matter()?;
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| {
|
||||
p.parse_arg()
|
||||
})?;
|
||||
let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?;
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
Ok((ident, inner_attrs, ast::ImplItemKind::Method(ast::MethodSig {
|
||||
generics: generics,
|
||||
abi: abi,
|
||||
explicit_self: explicit_self,
|
||||
unsafety: unsafety,
|
||||
constness: constness,
|
||||
decl: decl
|
||||
|
@ -12,7 +12,7 @@ pub use self::AnnNode::*;
|
||||
|
||||
use abi::{self, Abi};
|
||||
use ast::{self, TokenTree, BlockCheckMode, PatKind};
|
||||
use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
|
||||
use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
|
||||
use ast::Attribute;
|
||||
use attr::ThinAttributesExt;
|
||||
use util::parser::AssocOp;
|
||||
@ -382,13 +382,12 @@ pub fn fun_to_string(decl: &ast::FnDecl,
|
||||
unsafety: ast::Unsafety,
|
||||
constness: ast::Constness,
|
||||
name: ast::Ident,
|
||||
opt_explicit_self: Option<&ast::SelfKind>,
|
||||
generics: &ast::Generics)
|
||||
-> String {
|
||||
to_string(|s| {
|
||||
s.head("")?;
|
||||
s.print_fn(decl, unsafety, constness, Abi::Rust, Some(name),
|
||||
generics, opt_explicit_self, &ast::Visibility::Inherited)?;
|
||||
generics, &ast::Visibility::Inherited)?;
|
||||
s.end()?; // Close the head box
|
||||
s.end() // Close the outer box
|
||||
})
|
||||
@ -416,10 +415,6 @@ pub fn lit_to_string(l: &ast::Lit) -> String {
|
||||
to_string(|s| s.print_literal(l))
|
||||
}
|
||||
|
||||
pub fn explicit_self_to_string(explicit_self: &ast::SelfKind) -> String {
|
||||
to_string(|s| s.print_explicit_self(explicit_self, ast::Mutability::Immutable).map(|_| {}))
|
||||
}
|
||||
|
||||
pub fn variant_to_string(var: &ast::Variant) -> String {
|
||||
to_string(|s| s.print_variant(var))
|
||||
}
|
||||
@ -1005,8 +1000,7 @@ impl<'a> State<'a> {
|
||||
f.unsafety,
|
||||
&f.decl,
|
||||
None,
|
||||
&generics,
|
||||
None)?;
|
||||
&generics)?;
|
||||
}
|
||||
ast::TyKind::Path(None, ref path) => {
|
||||
self.print_path(path, false, 0)?;
|
||||
@ -1036,6 +1030,9 @@ impl<'a> State<'a> {
|
||||
ast::TyKind::Infer => {
|
||||
word(&mut self.s, "_")?;
|
||||
}
|
||||
ast::TyKind::ImplicitSelf => {
|
||||
unreachable!();
|
||||
}
|
||||
ast::TyKind::Mac(ref m) => {
|
||||
self.print_mac(m, token::Paren)?;
|
||||
}
|
||||
@ -1054,7 +1051,7 @@ impl<'a> State<'a> {
|
||||
self.print_fn(decl, ast::Unsafety::Normal,
|
||||
ast::Constness::NotConst,
|
||||
Abi::Rust, Some(item.ident),
|
||||
generics, None, &item.vis)?;
|
||||
generics, &item.vis)?;
|
||||
self.end()?; // end head-ibox
|
||||
word(&mut self.s, ";")?;
|
||||
self.end() // end the outer fn box
|
||||
@ -1182,7 +1179,6 @@ impl<'a> State<'a> {
|
||||
abi,
|
||||
Some(item.ident),
|
||||
typarams,
|
||||
None,
|
||||
&item.vis
|
||||
)?;
|
||||
word(&mut self.s, " ")?;
|
||||
@ -1522,7 +1518,6 @@ impl<'a> State<'a> {
|
||||
m.abi,
|
||||
Some(ident),
|
||||
&m.generics,
|
||||
None,
|
||||
vis)
|
||||
}
|
||||
|
||||
@ -2021,7 +2016,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
ast::ExprKind::While(ref test, ref blk, opt_ident) => {
|
||||
if let Some(ident) = opt_ident {
|
||||
self.print_ident(ident)?;
|
||||
self.print_ident(ident.node)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("while")?;
|
||||
@ -2031,7 +2026,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => {
|
||||
if let Some(ident) = opt_ident {
|
||||
self.print_ident(ident)?;
|
||||
self.print_ident(ident.node)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("while let")?;
|
||||
@ -2044,7 +2039,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => {
|
||||
if let Some(ident) = opt_ident {
|
||||
self.print_ident(ident)?;
|
||||
self.print_ident(ident.node)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("for")?;
|
||||
@ -2057,7 +2052,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
ast::ExprKind::Loop(ref blk, opt_ident) => {
|
||||
if let Some(ident) = opt_ident {
|
||||
self.print_ident(ident)?;
|
||||
self.print_ident(ident.node)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("loop")?;
|
||||
@ -2472,17 +2467,23 @@ impl<'a> State<'a> {
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
PatKind::TupleStruct(ref path, ref args_) => {
|
||||
PatKind::TupleStruct(ref path, ref elts, ddpos) => {
|
||||
self.print_path(path, true, 0)?;
|
||||
match *args_ {
|
||||
None => word(&mut self.s, "(..)")?,
|
||||
Some(ref args) => {
|
||||
self.popen()?;
|
||||
self.commasep(Inconsistent, &args[..],
|
||||
|s, p| s.print_pat(&p))?;
|
||||
self.pclose()?;
|
||||
self.popen()?;
|
||||
if let Some(ddpos) = ddpos {
|
||||
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
|
||||
if ddpos != 0 {
|
||||
self.word_space(",")?;
|
||||
}
|
||||
word(&mut self.s, "..")?;
|
||||
if ddpos != elts.len() {
|
||||
word(&mut self.s, ",")?;
|
||||
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
|
||||
}
|
||||
} else {
|
||||
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
|
||||
}
|
||||
self.pclose()?;
|
||||
}
|
||||
PatKind::Path(ref path) => {
|
||||
self.print_path(path, true, 0)?;
|
||||
@ -2513,13 +2514,23 @@ impl<'a> State<'a> {
|
||||
space(&mut self.s)?;
|
||||
word(&mut self.s, "}")?;
|
||||
}
|
||||
PatKind::Tup(ref elts) => {
|
||||
PatKind::Tuple(ref elts, ddpos) => {
|
||||
self.popen()?;
|
||||
self.commasep(Inconsistent,
|
||||
&elts[..],
|
||||
|s, p| s.print_pat(&p))?;
|
||||
if elts.len() == 1 {
|
||||
word(&mut self.s, ",")?;
|
||||
if let Some(ddpos) = ddpos {
|
||||
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
|
||||
if ddpos != 0 {
|
||||
self.word_space(",")?;
|
||||
}
|
||||
word(&mut self.s, "..")?;
|
||||
if ddpos != elts.len() {
|
||||
word(&mut self.s, ",")?;
|
||||
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
|
||||
}
|
||||
} else {
|
||||
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
|
||||
if elts.len() == 1 {
|
||||
word(&mut self.s, ",")?;
|
||||
}
|
||||
}
|
||||
self.pclose()?;
|
||||
}
|
||||
@ -2610,29 +2621,25 @@ impl<'a> State<'a> {
|
||||
self.end() // close enclosing cbox
|
||||
}
|
||||
|
||||
// Returns whether it printed anything
|
||||
fn print_explicit_self(&mut self,
|
||||
explicit_self: &ast::SelfKind,
|
||||
mutbl: ast::Mutability) -> io::Result<bool> {
|
||||
self.print_mutability(mutbl)?;
|
||||
match *explicit_self {
|
||||
ast::SelfKind::Static => { return Ok(false); }
|
||||
ast::SelfKind::Value(_) => {
|
||||
word(&mut self.s, "self")?;
|
||||
fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) -> io::Result<()> {
|
||||
match explicit_self.node {
|
||||
SelfKind::Value(m) => {
|
||||
self.print_mutability(m)?;
|
||||
word(&mut self.s, "self")
|
||||
}
|
||||
ast::SelfKind::Region(ref lt, m, _) => {
|
||||
SelfKind::Region(ref lt, m) => {
|
||||
word(&mut self.s, "&")?;
|
||||
self.print_opt_lifetime(lt)?;
|
||||
self.print_mutability(m)?;
|
||||
word(&mut self.s, "self")?;
|
||||
word(&mut self.s, "self")
|
||||
}
|
||||
ast::SelfKind::Explicit(ref typ, _) => {
|
||||
SelfKind::Explicit(ref typ, m) => {
|
||||
self.print_mutability(m)?;
|
||||
word(&mut self.s, "self")?;
|
||||
self.word_space(":")?;
|
||||
self.print_type(&typ)?;
|
||||
self.print_type(&typ)
|
||||
}
|
||||
}
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
pub fn print_fn(&mut self,
|
||||
@ -2642,7 +2649,6 @@ impl<'a> State<'a> {
|
||||
abi: abi::Abi,
|
||||
name: Option<ast::Ident>,
|
||||
generics: &ast::Generics,
|
||||
opt_explicit_self: Option<&ast::SelfKind>,
|
||||
vis: &ast::Visibility) -> io::Result<()> {
|
||||
self.print_fn_header_info(unsafety, constness, abi, vis)?;
|
||||
|
||||
@ -2651,21 +2657,14 @@ impl<'a> State<'a> {
|
||||
self.print_ident(name)?;
|
||||
}
|
||||
self.print_generics(generics)?;
|
||||
self.print_fn_args_and_ret(decl, opt_explicit_self)?;
|
||||
self.print_fn_args_and_ret(decl)?;
|
||||
self.print_where_clause(&generics.where_clause)
|
||||
}
|
||||
|
||||
pub fn print_fn_args(&mut self, decl: &ast::FnDecl,
|
||||
_: Option<&ast::SelfKind>,
|
||||
is_closure: bool) -> io::Result<()> {
|
||||
self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, is_closure))
|
||||
}
|
||||
|
||||
pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl,
|
||||
opt_explicit_self: Option<&ast::SelfKind>)
|
||||
pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl)
|
||||
-> io::Result<()> {
|
||||
self.popen()?;
|
||||
self.print_fn_args(decl, opt_explicit_self, false)?;
|
||||
self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?;
|
||||
if decl.variadic {
|
||||
word(&mut self.s, ", ...")?;
|
||||
}
|
||||
@ -2679,7 +2678,7 @@ impl<'a> State<'a> {
|
||||
decl: &ast::FnDecl)
|
||||
-> io::Result<()> {
|
||||
word(&mut self.s, "|")?;
|
||||
self.print_fn_args(decl, None, true)?;
|
||||
self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?;
|
||||
word(&mut self.s, "|")?;
|
||||
|
||||
if let ast::FunctionRetTy::Default(..) = decl.output {
|
||||
@ -2929,17 +2928,14 @@ impl<'a> State<'a> {
|
||||
match input.ty.node {
|
||||
ast::TyKind::Infer if is_closure => self.print_pat(&input.pat)?,
|
||||
_ => {
|
||||
let (mutbl, invalid) = match input.pat.node {
|
||||
PatKind::Ident(ast::BindingMode::ByValue(mutbl), ident, _) |
|
||||
PatKind::Ident(ast::BindingMode::ByRef(mutbl), ident, _) => {
|
||||
(mutbl, ident.node.name == keywords::Invalid.name())
|
||||
}
|
||||
_ => (ast::Mutability::Immutable, false)
|
||||
};
|
||||
|
||||
if let Some(eself) = input.to_self() {
|
||||
self.print_explicit_self(&eself.node, mutbl)?;
|
||||
self.print_explicit_self(&eself)?;
|
||||
} else {
|
||||
let invalid = if let PatKind::Ident(_, ident, _) = input.pat.node {
|
||||
ident.node.name == keywords::Invalid.name()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if !invalid {
|
||||
self.print_pat(&input.pat)?;
|
||||
word(&mut self.s, ":")?;
|
||||
@ -2980,8 +2976,7 @@ impl<'a> State<'a> {
|
||||
unsafety: ast::Unsafety,
|
||||
decl: &ast::FnDecl,
|
||||
name: Option<ast::Ident>,
|
||||
generics: &ast::Generics,
|
||||
opt_explicit_self: Option<&ast::SelfKind>)
|
||||
generics: &ast::Generics)
|
||||
-> io::Result<()> {
|
||||
self.ibox(INDENT_UNIT)?;
|
||||
if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
|
||||
@ -3002,7 +2997,6 @@ impl<'a> State<'a> {
|
||||
abi,
|
||||
name,
|
||||
&generics,
|
||||
opt_explicit_self,
|
||||
&ast::Visibility::Inherited)?;
|
||||
self.end()
|
||||
}
|
||||
@ -3126,8 +3120,7 @@ mod tests {
|
||||
let generics = ast::Generics::default();
|
||||
assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal,
|
||||
ast::Constness::NotConst,
|
||||
abba_ident,
|
||||
None, &generics),
|
||||
abba_ident, &generics),
|
||||
"fn abba()");
|
||||
}
|
||||
|
||||
|
@ -129,10 +129,6 @@ impl<'v> Visitor<'v> for NodeCounter {
|
||||
self.count += 1;
|
||||
walk_lifetime_def(self, lifetime)
|
||||
}
|
||||
fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) {
|
||||
self.count += 1;
|
||||
walk_explicit_self(self, es)
|
||||
}
|
||||
fn visit_mac(&mut self, _mac: &'v Mac) {
|
||||
self.count += 1;
|
||||
walk_mac(self, _mac)
|
||||
|
@ -26,7 +26,7 @@
|
||||
use abi::Abi;
|
||||
use ast::*;
|
||||
use attr::ThinAttributesExt;
|
||||
use codemap::Span;
|
||||
use codemap::{Span, Spanned};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum FnKind<'a> {
|
||||
@ -99,9 +99,6 @@ pub trait Visitor<'v> : Sized {
|
||||
fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
|
||||
walk_lifetime_def(self, lifetime)
|
||||
}
|
||||
fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) {
|
||||
walk_explicit_self(self, es)
|
||||
}
|
||||
fn visit_mac(&mut self, _mac: &'v Mac) {
|
||||
panic!("visit_mac disabled by default");
|
||||
// NB: see note about macros above.
|
||||
@ -149,17 +146,24 @@ macro_rules! walk_list {
|
||||
}
|
||||
|
||||
pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
|
||||
for name in opt_name {
|
||||
if let Some(name) = opt_name {
|
||||
visitor.visit_name(span, name);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
|
||||
for ident in opt_ident {
|
||||
if let Some(ident) = opt_ident {
|
||||
visitor.visit_ident(span, ident);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_opt_sp_ident<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
opt_sp_ident: &Option<Spanned<Ident>>) {
|
||||
if let Some(ref sp_ident) = *opt_sp_ident {
|
||||
visitor.visit_ident(sp_ident.span, sp_ident.node);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) {
|
||||
visitor.visit_name(span, ident.name);
|
||||
}
|
||||
@ -196,24 +200,6 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
|
||||
}
|
||||
|
||||
pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
explicit_self: &'v ExplicitSelf) {
|
||||
match explicit_self.node {
|
||||
SelfKind::Static => {},
|
||||
SelfKind::Value(ident) => {
|
||||
visitor.visit_ident(explicit_self.span, ident)
|
||||
}
|
||||
SelfKind::Region(ref opt_lifetime, _, ident) => {
|
||||
visitor.visit_ident(explicit_self.span, ident);
|
||||
walk_list!(visitor, visit_lifetime, opt_lifetime);
|
||||
}
|
||||
SelfKind::Explicit(ref typ, ident) => {
|
||||
visitor.visit_ident(explicit_self.span, ident);
|
||||
visitor.visit_ty(typ)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
|
||||
trait_ref: &'v PolyTraitRef,
|
||||
_modifier: &'v TraitBoundModifier)
|
||||
@ -369,7 +355,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
||||
TyKind::Typeof(ref expression) => {
|
||||
visitor.visit_expr(expression)
|
||||
}
|
||||
TyKind::Infer => {}
|
||||
TyKind::Infer | TyKind::ImplicitSelf => {}
|
||||
TyKind::Mac(ref mac) => {
|
||||
visitor.visit_mac(mac)
|
||||
}
|
||||
@ -423,11 +409,9 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
|
||||
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
|
||||
match pattern.node {
|
||||
PatKind::TupleStruct(ref path, ref opt_children) => {
|
||||
PatKind::TupleStruct(ref path, ref children, _) => {
|
||||
visitor.visit_path(path, pattern.id);
|
||||
if let Some(ref children) = *opt_children {
|
||||
walk_list!(visitor, visit_pat, children);
|
||||
}
|
||||
walk_list!(visitor, visit_pat, children);
|
||||
}
|
||||
PatKind::Path(ref path) => {
|
||||
visitor.visit_path(path, pattern.id);
|
||||
@ -443,7 +427,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
|
||||
visitor.visit_pat(&field.node.pat)
|
||||
}
|
||||
}
|
||||
PatKind::Tup(ref tuple_elements) => {
|
||||
PatKind::Tuple(ref tuple_elements, _) => {
|
||||
walk_list!(visitor, visit_pat, tuple_elements);
|
||||
}
|
||||
PatKind::Box(ref subpattern) |
|
||||
@ -553,7 +537,6 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
}
|
||||
FnKind::Method(_, ref sig, _) => {
|
||||
visitor.visit_generics(&sig.generics);
|
||||
visitor.visit_explicit_self(&sig.explicit_self);
|
||||
}
|
||||
FnKind::Closure => {}
|
||||
}
|
||||
@ -578,7 +561,6 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
|
||||
walk_list!(visitor, visit_expr, default);
|
||||
}
|
||||
TraitItemKind::Method(ref sig, None) => {
|
||||
visitor.visit_explicit_self(&sig.explicit_self);
|
||||
visitor.visit_generics(&sig.generics);
|
||||
walk_fn_decl(visitor, &sig.decl);
|
||||
}
|
||||
@ -712,10 +694,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||
visitor.visit_block(if_block);
|
||||
walk_list!(visitor, visit_expr, optional_else);
|
||||
}
|
||||
ExprKind::While(ref subexpression, ref block, opt_ident) => {
|
||||
ExprKind::While(ref subexpression, ref block, ref opt_sp_ident) => {
|
||||
visitor.visit_expr(subexpression);
|
||||
visitor.visit_block(block);
|
||||
walk_opt_ident(visitor, expression.span, opt_ident)
|
||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||
}
|
||||
ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
|
||||
visitor.visit_pat(pattern);
|
||||
@ -723,21 +705,21 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||
visitor.visit_block(if_block);
|
||||
walk_list!(visitor, visit_expr, optional_else);
|
||||
}
|
||||
ExprKind::WhileLet(ref pattern, ref subexpression, ref block, opt_ident) => {
|
||||
ExprKind::WhileLet(ref pattern, ref subexpression, ref block, ref opt_sp_ident) => {
|
||||
visitor.visit_pat(pattern);
|
||||
visitor.visit_expr(subexpression);
|
||||
visitor.visit_block(block);
|
||||
walk_opt_ident(visitor, expression.span, opt_ident)
|
||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||
}
|
||||
ExprKind::ForLoop(ref pattern, ref subexpression, ref block, opt_ident) => {
|
||||
ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_sp_ident) => {
|
||||
visitor.visit_pat(pattern);
|
||||
visitor.visit_expr(subexpression);
|
||||
visitor.visit_block(block);
|
||||
walk_opt_ident(visitor, expression.span, opt_ident)
|
||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||
}
|
||||
ExprKind::Loop(ref block, opt_ident) => {
|
||||
ExprKind::Loop(ref block, ref opt_sp_ident) => {
|
||||
visitor.visit_block(block);
|
||||
walk_opt_ident(visitor, expression.span, opt_ident)
|
||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||
}
|
||||
ExprKind::Match(ref subexpression, ref arms) => {
|
||||
visitor.visit_expr(subexpression);
|
||||
@ -781,9 +763,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||
visitor.visit_path(path, expression.id)
|
||||
}
|
||||
ExprKind::Break(ref opt_sp_ident) | ExprKind::Again(ref opt_sp_ident) => {
|
||||
for sp_ident in opt_sp_ident {
|
||||
visitor.visit_ident(sp_ident.span, sp_ident.node);
|
||||
}
|
||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||
}
|
||||
ExprKind::Ret(ref optional_expression) => {
|
||||
walk_list!(visitor, visit_expr, optional_expression);
|
||||
|
@ -197,7 +197,7 @@ use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::ext::base::{ExtCtxt, Annotatable};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::codemap::{self, DUMMY_SP};
|
||||
use syntax::codemap::{self, respan, DUMMY_SP};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::errors::Handler;
|
||||
use syntax::util::move_map::MoveMap;
|
||||
@ -806,25 +806,21 @@ impl<'a> MethodDef<'a> {
|
||||
trait_: &TraitDef,
|
||||
type_ident: Ident,
|
||||
generics: &Generics)
|
||||
-> (ast::ExplicitSelf, Vec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
|
||||
-> (Option<ast::ExplicitSelf>, Vec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
|
||||
|
||||
let mut self_args = Vec::new();
|
||||
let mut nonself_args = Vec::new();
|
||||
let mut arg_tys = Vec::new();
|
||||
let mut nonstatic = false;
|
||||
|
||||
let ast_explicit_self = match self.explicit_self {
|
||||
Some(ref self_ptr) => {
|
||||
let (self_expr, explicit_self) =
|
||||
ty::get_explicit_self(cx, trait_.span, self_ptr);
|
||||
let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| {
|
||||
let (self_expr, explicit_self) = ty::get_explicit_self(cx, trait_.span, self_ptr);
|
||||
|
||||
self_args.push(self_expr);
|
||||
nonstatic = true;
|
||||
self_args.push(self_expr);
|
||||
nonstatic = true;
|
||||
|
||||
explicit_self
|
||||
}
|
||||
None => codemap::respan(trait_.span, ast::SelfKind::Static),
|
||||
};
|
||||
explicit_self
|
||||
});
|
||||
|
||||
for (i, ty) in self.args.iter().enumerate() {
|
||||
let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
|
||||
@ -857,24 +853,20 @@ impl<'a> MethodDef<'a> {
|
||||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
abi: Abi,
|
||||
explicit_self: ast::ExplicitSelf,
|
||||
explicit_self: Option<ast::ExplicitSelf>,
|
||||
arg_types: Vec<(Ident, P<ast::Ty>)> ,
|
||||
body: P<Expr>) -> ast::ImplItem {
|
||||
|
||||
// create the generics that aren't for Self
|
||||
let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
|
||||
|
||||
let self_arg = match explicit_self.node {
|
||||
ast::SelfKind::Static => None,
|
||||
// creating fresh self id
|
||||
_ => Some(ast::Arg::from_self(explicit_self.clone(), trait_.span,
|
||||
ast::Mutability::Immutable)),
|
||||
};
|
||||
let args = {
|
||||
let args = arg_types.into_iter().map(|(name, ty)| {
|
||||
cx.arg(trait_.span, name, ty)
|
||||
});
|
||||
self_arg.into_iter().chain(args).collect()
|
||||
let self_args = explicit_self.map(|explicit_self| {
|
||||
ast::Arg::from_self(explicit_self, respan(trait_.span, keywords::SelfValue.ident()))
|
||||
});
|
||||
let nonself_args = arg_types.into_iter()
|
||||
.map(|(name, ty)| cx.arg(trait_.span, name, ty));
|
||||
self_args.into_iter().chain(nonself_args).collect()
|
||||
};
|
||||
|
||||
let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident);
|
||||
@ -900,7 +892,6 @@ impl<'a> MethodDef<'a> {
|
||||
node: ast::ImplItemKind::Method(ast::MethodSig {
|
||||
generics: fn_generics,
|
||||
abi: abi,
|
||||
explicit_self: explicit_self,
|
||||
unsafety: unsafety,
|
||||
constness: ast::Constness::NotConst,
|
||||
decl: fn_decl
|
||||
|
@ -15,11 +15,10 @@ pub use self::PtrTy::*;
|
||||
pub use self::Ty::*;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::ast::{Expr,Generics,Ident};
|
||||
use syntax::ast::{Expr, Generics, Ident, SelfKind};
|
||||
use syntax::ext::base::ExtCtxt;
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::codemap::{Span,respan};
|
||||
use syntax::parse::token::keywords;
|
||||
use syntax::ptr::P;
|
||||
|
||||
/// The types of pointers
|
||||
@ -258,12 +257,11 @@ impl<'a> LifetimeBounds<'a> {
|
||||
|
||||
pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
|
||||
-> (P<Expr>, ast::ExplicitSelf) {
|
||||
// this constructs a fresh `self` path, which will match the fresh `self` binding
|
||||
// created below.
|
||||
// this constructs a fresh `self` path
|
||||
let self_path = cx.expr_self(span);
|
||||
match *self_ptr {
|
||||
None => {
|
||||
(self_path, respan(span, ast::SelfKind::Value(keywords::SelfValue.ident())))
|
||||
(self_path, respan(span, SelfKind::Value(ast::Mutability::Immutable)))
|
||||
}
|
||||
Some(ref ptr) => {
|
||||
let self_ty = respan(
|
||||
@ -271,7 +269,7 @@ pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
|
||||
match *ptr {
|
||||
Borrowed(ref lt, mutbl) => {
|
||||
let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
|
||||
ast::SelfKind::Region(lt, mutbl, keywords::SelfValue.ident())
|
||||
SelfKind::Region(lt, mutbl)
|
||||
}
|
||||
Raw(_) => cx.span_bug(span, "attempted to use *self in deriving definition")
|
||||
});
|
||||
|
@ -18,12 +18,12 @@ struct S;
|
||||
fn main() {
|
||||
match Foo::Baz {
|
||||
Foo::Bar => {}
|
||||
//~^ ERROR this pattern has 0 fields, but the corresponding variant
|
||||
//~^ ERROR `Foo::Bar` does not name a tuple variant or a tuple struct
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match S {
|
||||
S(()) => {}
|
||||
//~^ ERROR this pattern has 1 field, but the corresponding struct
|
||||
//~^ ERROR `S` does not name a tuple variant or a tuple struct
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ fn main() {
|
||||
color::rgb(_, _, _) => { }
|
||||
color::cmyk(_, _, _, _) => { }
|
||||
color::no_color(_) => { }
|
||||
//~^ ERROR this pattern has 1 field, but the corresponding variant has no fields
|
||||
//~^ ERROR `color::no_color` does not name a tuple variant or a tuple struct
|
||||
}
|
||||
}
|
||||
}
|
||||
|
27
src/test/compile-fail/pat-tuple-bad-type.rs
Normal file
27
src/test/compile-fail/pat-tuple-bad-type.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
|
||||
fn main() {
|
||||
let x;
|
||||
|
||||
match x {
|
||||
(..) => {} //~ ERROR the type of this value must be known in this context
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match 0u8 {
|
||||
(..) => {} //~ ERROR mismatched types
|
||||
_ => {}
|
||||
}
|
||||
|
||||
x = 10;
|
||||
}
|
17
src/test/compile-fail/pat-tuple-feature-gate.rs
Normal file
17
src/test/compile-fail/pat-tuple-feature-gate.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2016 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 {
|
||||
(..) => {} //~ ERROR `..` in tuple patterns is experimental
|
||||
(pat, ..) => {} //~ ERROR `..` in tuple patterns is experimental
|
||||
S(pat, ..) => {} //~ ERROR `..` in tuple struct patterns is experimental
|
||||
}
|
||||
}
|
28
src/test/compile-fail/pat-tuple-overfield.rs
Normal file
28
src/test/compile-fail/pat-tuple-overfield.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
|
||||
struct S(u8, u8, u8);
|
||||
|
||||
fn main() {
|
||||
match (1, 2, 3) {
|
||||
(1, 2, 3, 4) => {} //~ ERROR mismatched types
|
||||
(1, 2, .., 3, 4) => {} //~ ERROR mismatched types
|
||||
_ => {}
|
||||
}
|
||||
match S(1, 2, 3) {
|
||||
S(1, 2, 3, 4) => {}
|
||||
//~^ ERROR this pattern has 4 fields, but the corresponding struct has 3 fields
|
||||
S(1, 2, .., 3, 4) => {}
|
||||
//~^ ERROR this pattern has 4 fields, but the corresponding struct has 3 fields
|
||||
_ => {}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ fn f(_c: char) {}
|
||||
fn main() {
|
||||
match A::B(1, 2) {
|
||||
A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but
|
||||
A::D(_) => (), //~ ERROR this pattern has 1 field, but
|
||||
A::D(_) => (), //~ ERROR `A::D` does not name a tuple variant or a tuple struct
|
||||
_ => ()
|
||||
}
|
||||
match 'c' {
|
||||
|
@ -9,6 +9,5 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
let Test(&desc[..]) = x; //~ error: expected one of `,` or `@`, found `[`
|
||||
//~^ ERROR expected one of `:`, `;`, `=`, or `@`, found `[`
|
||||
let Test(&desc[..]) = x; //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
|
||||
}
|
||||
|
@ -9,6 +9,5 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
for thing(x[]) in foo {} //~ error: expected one of `,` or `@`, found `[`
|
||||
//~^ ERROR expected one of `@` or `in`, found `[`
|
||||
for thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
|
||||
}
|
||||
|
@ -8,15 +8,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
enum Number {
|
||||
Zero,
|
||||
One(u32)
|
||||
}
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
fn main() {
|
||||
let x = Number::Zero;
|
||||
match x {
|
||||
Number::Zero(inside) => {}, //~ ERROR E0024
|
||||
Number::One(inside) => {},
|
||||
match 0 {
|
||||
(, ..) => {} //~ ERROR expected pattern, found `,`
|
||||
}
|
||||
}
|
17
src/test/parse-fail/pat-tuple-2.rs
Normal file
17
src/test/parse-fail/pat-tuple-2.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
fn main() {
|
||||
match 0 {
|
||||
(pat, ..,) => {} //~ ERROR expected pattern, found `)`
|
||||
}
|
||||
}
|
17
src/test/parse-fail/pat-tuple-3.rs
Normal file
17
src/test/parse-fail/pat-tuple-3.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
fn main() {
|
||||
match 0 {
|
||||
(.., pat, ..) => {} //~ ERROR `..` can only be used once per tuple or tuple struct pattern
|
||||
}
|
||||
}
|
17
src/test/parse-fail/pat-tuple-4.rs
Normal file
17
src/test/parse-fail/pat-tuple-4.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
fn main() {
|
||||
match 0 {
|
||||
(.. pat) => {} //~ ERROR expected one of `)` or `,`, found `pat`
|
||||
}
|
||||
}
|
17
src/test/parse-fail/pat-tuple-5.rs
Normal file
17
src/test/parse-fail/pat-tuple-5.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
fn main() {
|
||||
match 0 {
|
||||
(pat ..) => {} //~ ERROR expected one of `)`, `,`, or `@`, found `..`
|
||||
}
|
||||
}
|
17
src/test/parse-fail/pat-tuple-6.rs
Normal file
17
src/test/parse-fail/pat-tuple-6.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
fn main() {
|
||||
match 0 {
|
||||
(pat) => {} //~ ERROR expected one of `,` or `@`, found `)`
|
||||
}
|
||||
}
|
104
src/test/run-pass/pat-tuple-1.rs
Normal file
104
src/test/run-pass/pat-tuple-1.rs
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
|
||||
fn tuple() {
|
||||
let x = (1, 2, 3);
|
||||
match x {
|
||||
(a, b, ..) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
(.., b, c) => {
|
||||
assert_eq!(b, 2);
|
||||
assert_eq!(c, 3);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
(a, .., c) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(c, 3);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
(a, b, c) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
assert_eq!(c, 3);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
(a, b, c, ..) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
assert_eq!(c, 3);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
(.., a, b, c) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
assert_eq!(c, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn tuple_struct() {
|
||||
struct S(u8, u8, u8);
|
||||
|
||||
let x = S(1, 2, 3);
|
||||
match x {
|
||||
S(a, b, ..) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
S(.., b, c) => {
|
||||
assert_eq!(b, 2);
|
||||
assert_eq!(c, 3);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
S(a, .., c) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(c, 3);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
S(a, b, c) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
assert_eq!(c, 3);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
S(a, b, c, ..) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
assert_eq!(c, 3);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
S(.., a, b, c) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
assert_eq!(c, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tuple();
|
||||
tuple_struct();
|
||||
}
|
34
src/test/run-pass/pat-tuple-2.rs
Normal file
34
src/test/run-pass/pat-tuple-2.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
|
||||
fn tuple() {
|
||||
let x = (1,);
|
||||
match x {
|
||||
(2, ..) => panic!(),
|
||||
(..) => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn tuple_struct() {
|
||||
struct S(u8);
|
||||
|
||||
let x = S(1);
|
||||
match x {
|
||||
S(2, ..) => panic!(),
|
||||
S(..) => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tuple();
|
||||
tuple_struct();
|
||||
}
|
40
src/test/run-pass/pat-tuple-3.rs
Normal file
40
src/test/run-pass/pat-tuple-3.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
|
||||
fn tuple() {
|
||||
let x = (1, 2, 3);
|
||||
let branch = match x {
|
||||
(1, 1, ..) => 0,
|
||||
(1, 2, 3, ..) => 1,
|
||||
(1, 2, ..) => 2,
|
||||
_ => 3
|
||||
};
|
||||
assert_eq!(branch, 1);
|
||||
}
|
||||
|
||||
fn tuple_struct() {
|
||||
struct S(u8, u8, u8);
|
||||
|
||||
let x = S(1, 2, 3);
|
||||
let branch = match x {
|
||||
S(1, 1, ..) => 0,
|
||||
S(1, 2, 3, ..) => 1,
|
||||
S(1, 2, ..) => 2,
|
||||
_ => 3
|
||||
};
|
||||
assert_eq!(branch, 1);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tuple();
|
||||
tuple_struct();
|
||||
}
|
68
src/test/run-pass/pat-tuple-4.rs
Normal file
68
src/test/run-pass/pat-tuple-4.rs
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
|
||||
fn tuple() {
|
||||
let x = (1, 2, 3);
|
||||
match x {
|
||||
(1, 2, 4) => unreachable!(),
|
||||
(0, 2, 3, ..) => unreachable!(),
|
||||
(0, .., 3) => unreachable!(),
|
||||
(0, ..) => unreachable!(),
|
||||
(1, 2, 3) => (),
|
||||
(_, _, _) => unreachable!(),
|
||||
}
|
||||
match x {
|
||||
(..) => (),
|
||||
}
|
||||
match x {
|
||||
(_, _, _, ..) => (),
|
||||
}
|
||||
match x {
|
||||
(a, b, c) => {
|
||||
assert_eq!(1, a);
|
||||
assert_eq!(2, b);
|
||||
assert_eq!(3, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn tuple_struct() {
|
||||
struct S(u8, u8, u8);
|
||||
|
||||
let x = S(1, 2, 3);
|
||||
match x {
|
||||
S(1, 2, 4) => unreachable!(),
|
||||
S(0, 2, 3, ..) => unreachable!(),
|
||||
S(0, .., 3) => unreachable!(),
|
||||
S(0, ..) => unreachable!(),
|
||||
S(1, 2, 3) => (),
|
||||
S(_, _, _) => unreachable!(),
|
||||
}
|
||||
match x {
|
||||
S(..) => (),
|
||||
}
|
||||
match x {
|
||||
S(_, _, _, ..) => (),
|
||||
}
|
||||
match x {
|
||||
S(a, b, c) => {
|
||||
assert_eq!(1, a);
|
||||
assert_eq!(2, b);
|
||||
assert_eq!(3, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tuple();
|
||||
tuple_struct();
|
||||
}
|
40
src/test/run-pass/pat-tuple-5.rs
Normal file
40
src/test/run-pass/pat-tuple-5.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
|
||||
fn tuple() {
|
||||
struct S;
|
||||
struct Z;
|
||||
struct W;
|
||||
let x = (S, Z, W);
|
||||
match x { (S, ..) => {} }
|
||||
match x { (.., W) => {} }
|
||||
match x { (S, .., W) => {} }
|
||||
match x { (.., Z, _) => {} }
|
||||
}
|
||||
|
||||
fn tuple_struct() {
|
||||
struct SS(S, Z, W);
|
||||
|
||||
struct S;
|
||||
struct Z;
|
||||
struct W;
|
||||
let x = SS(S, Z, W);
|
||||
match x { SS(S, ..) => {} }
|
||||
match x { SS(.., W) => {} }
|
||||
match x { SS(S, .., W) => {} }
|
||||
match x { SS(.., Z, _) => {} }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tuple();
|
||||
tuple_struct();
|
||||
}
|
56
src/test/run-pass/pat-tuple-6.rs
Normal file
56
src/test/run-pass/pat-tuple-6.rs
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
|
||||
fn tuple() {
|
||||
let x = (1, 2, 3, 4, 5);
|
||||
match x {
|
||||
(a, .., b, c) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 4);
|
||||
assert_eq!(c, 5);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
(a, b, c, .., d) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
assert_eq!(c, 3);
|
||||
assert_eq!(d, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn tuple_struct() {
|
||||
struct S(u8, u8, u8, u8, u8);
|
||||
|
||||
let x = S(1, 2, 3, 4, 5);
|
||||
match x {
|
||||
S(a, .., b, c) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 4);
|
||||
assert_eq!(c, 5);
|
||||
}
|
||||
}
|
||||
match x {
|
||||
S(a, b, c, .., d) => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
assert_eq!(c, 3);
|
||||
assert_eq!(d, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tuple();
|
||||
tuple_struct();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user