mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Rollup merge of #62550 - Centril:rest-patterns, r=petrochenkov
Implement RFC 2707 + Parser recovery for range patterns Implement https://github.com/rust-lang/rfcs/pull/2707. - Add a new basic syntactic pattern form `ast::PatKind::Rest` (parsed as `..` or `DOTDOT`) and simplify `ast::PatKind::{Slice, Tuple, TupleStruct}` as a result. - Lower `ast::PatKind::Rest` in combination with the aforementioned `PatKind` variants as well as `PatKind::Ident`. The HIR remains unchanged for now (may be advisable to make slight adjustments later). - Refactor `parser.rs` wrt. parsing sequences and lists of things in the process. - Add parser recovery for range patterns of form `X..`, `X..=`, `X...`, `..Y`, `..=Y`, and `...Y`. This should make it easy to actually support these patterns semantically later if we so desire. cc https://github.com/rust-lang/rust/issues/62254 r? @petrochenkov
This commit is contained in:
commit
75e23ff411
@ -17,7 +17,7 @@ matched against that pattern. For example:
|
||||
fn is_symmetric(list: &[u32]) -> bool {
|
||||
match list {
|
||||
&[] | &[_] => true,
|
||||
&[x, ref inside.., y] if x == y => is_symmetric(inside),
|
||||
&[x, ref inside @ .., y] if x == y => is_symmetric(inside),
|
||||
&[..] => false,
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ use std::mem;
|
||||
use smallvec::SmallVec;
|
||||
use syntax::attr;
|
||||
use syntax::ast;
|
||||
use syntax::ptr::P as AstP;
|
||||
use syntax::ast::*;
|
||||
use syntax::errors;
|
||||
use syntax::ext::hygiene::ExpnId;
|
||||
@ -467,7 +468,7 @@ impl<'a> LoweringContext<'a> {
|
||||
fn visit_pat(&mut self, p: &'tcx Pat) {
|
||||
match p.node {
|
||||
// Doesn't generate a HIR node
|
||||
PatKind::Paren(..) => {},
|
||||
PatKind::Paren(..) | PatKind::Rest => {},
|
||||
_ => {
|
||||
if let Some(owner) = self.hir_id_owner {
|
||||
self.lctx.lower_node_id_with_owner(p.id, owner);
|
||||
@ -1156,7 +1157,7 @@ impl<'a> LoweringContext<'a> {
|
||||
&mut self,
|
||||
capture_clause: CaptureBy,
|
||||
closure_node_id: NodeId,
|
||||
ret_ty: Option<syntax::ptr::P<Ty>>,
|
||||
ret_ty: Option<AstP<Ty>>,
|
||||
span: Span,
|
||||
body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
|
||||
) -> hir::ExprKind {
|
||||
@ -4171,33 +4172,11 @@ impl<'a> LoweringContext<'a> {
|
||||
let node = match p.node {
|
||||
PatKind::Wild => hir::PatKind::Wild,
|
||||
PatKind::Ident(ref binding_mode, ident, ref sub) => {
|
||||
match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
|
||||
// `None` can occur in body-less function signatures
|
||||
res @ None | res @ Some(Res::Local(_)) => {
|
||||
let canonical_id = match res {
|
||||
Some(Res::Local(id)) => id,
|
||||
_ => p.id,
|
||||
};
|
||||
|
||||
hir::PatKind::Binding(
|
||||
self.lower_binding_mode(binding_mode),
|
||||
self.lower_node_id(canonical_id),
|
||||
ident,
|
||||
sub.as_ref().map(|x| self.lower_pat(x)),
|
||||
)
|
||||
}
|
||||
Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
P(hir::Path {
|
||||
span: ident.span,
|
||||
res: self.lower_res(res),
|
||||
segments: hir_vec![hir::PathSegment::from_ident(ident)],
|
||||
}),
|
||||
)),
|
||||
}
|
||||
let lower_sub = |this: &mut Self| sub.as_ref().map(|x| this.lower_pat(x));
|
||||
self.lower_pat_ident(p, binding_mode, ident, lower_sub)
|
||||
}
|
||||
PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
|
||||
PatKind::TupleStruct(ref path, ref pats, ddpos) => {
|
||||
PatKind::TupleStruct(ref path, ref pats) => {
|
||||
let qpath = self.lower_qpath(
|
||||
p.id,
|
||||
&None,
|
||||
@ -4205,11 +4184,8 @@ impl<'a> LoweringContext<'a> {
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::disallowed(),
|
||||
);
|
||||
hir::PatKind::TupleStruct(
|
||||
qpath,
|
||||
pats.iter().map(|x| self.lower_pat(x)).collect(),
|
||||
ddpos,
|
||||
)
|
||||
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
|
||||
hir::PatKind::TupleStruct(qpath, pats, ddpos)
|
||||
}
|
||||
PatKind::Path(ref qself, ref path) => {
|
||||
let qpath = self.lower_qpath(
|
||||
@ -4246,8 +4222,9 @@ impl<'a> LoweringContext<'a> {
|
||||
.collect();
|
||||
hir::PatKind::Struct(qpath, fs, etc)
|
||||
}
|
||||
PatKind::Tuple(ref elts, ddpos) => {
|
||||
hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
|
||||
PatKind::Tuple(ref pats) => {
|
||||
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
|
||||
hir::PatKind::Tuple(pats, ddpos)
|
||||
}
|
||||
PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
|
||||
PatKind::Ref(ref inner, mutbl) => {
|
||||
@ -4258,15 +4235,138 @@ impl<'a> LoweringContext<'a> {
|
||||
P(self.lower_expr(e2)),
|
||||
self.lower_range_end(end),
|
||||
),
|
||||
PatKind::Slice(ref before, ref slice, ref after) => hir::PatKind::Slice(
|
||||
before.iter().map(|x| self.lower_pat(x)).collect(),
|
||||
slice.as_ref().map(|x| self.lower_pat(x)),
|
||||
after.iter().map(|x| self.lower_pat(x)).collect(),
|
||||
),
|
||||
PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
|
||||
PatKind::Rest => {
|
||||
// If we reach here the `..` pattern is not semantically allowed.
|
||||
self.ban_illegal_rest_pat(p.span)
|
||||
}
|
||||
PatKind::Paren(ref inner) => return self.lower_pat(inner),
|
||||
PatKind::Mac(_) => panic!("Shouldn't exist here"),
|
||||
};
|
||||
|
||||
self.pat_with_node_id_of(p, node)
|
||||
}
|
||||
|
||||
fn lower_pat_tuple(
|
||||
&mut self,
|
||||
pats: &[AstP<Pat>],
|
||||
ctx: &str,
|
||||
) -> (HirVec<P<hir::Pat>>, Option<usize>) {
|
||||
let mut elems = Vec::with_capacity(pats.len());
|
||||
let mut rest = None;
|
||||
|
||||
let mut iter = pats.iter().enumerate();
|
||||
while let Some((idx, pat)) = iter.next() {
|
||||
// Interpret the first `..` pattern as a subtuple pattern.
|
||||
if pat.is_rest() {
|
||||
rest = Some((idx, pat.span));
|
||||
break;
|
||||
}
|
||||
// It was not a subslice pattern so lower it normally.
|
||||
elems.push(self.lower_pat(pat));
|
||||
}
|
||||
|
||||
while let Some((_, pat)) = iter.next() {
|
||||
// There was a previous subtuple pattern; make sure we don't allow more.
|
||||
if pat.is_rest() {
|
||||
self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx);
|
||||
} else {
|
||||
elems.push(self.lower_pat(pat));
|
||||
}
|
||||
}
|
||||
|
||||
(elems.into(), rest.map(|(ddpos, _)| ddpos))
|
||||
}
|
||||
|
||||
fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind {
|
||||
let mut before = Vec::new();
|
||||
let mut after = Vec::new();
|
||||
let mut slice = None;
|
||||
let mut prev_rest_span = None;
|
||||
|
||||
let mut iter = pats.iter();
|
||||
while let Some(pat) = iter.next() {
|
||||
// Interpret the first `((ref mut?)? x @)? ..` pattern as a subslice pattern.
|
||||
match pat.node {
|
||||
PatKind::Rest => {
|
||||
prev_rest_span = Some(pat.span);
|
||||
slice = Some(self.pat_wild_with_node_id_of(pat));
|
||||
break;
|
||||
},
|
||||
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
|
||||
prev_rest_span = Some(sub.span);
|
||||
let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
|
||||
let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
|
||||
slice = Some(self.pat_with_node_id_of(pat, node));
|
||||
break;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// It was not a subslice pattern so lower it normally.
|
||||
before.push(self.lower_pat(pat));
|
||||
}
|
||||
|
||||
while let Some(pat) = iter.next() {
|
||||
// There was a previous subslice pattern; make sure we don't allow more.
|
||||
let rest_span = match pat.node {
|
||||
PatKind::Rest => Some(pat.span),
|
||||
PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
|
||||
// The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
|
||||
after.push(self.pat_wild_with_node_id_of(pat));
|
||||
Some(sub.span)
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
if let Some(rest_span) = rest_span {
|
||||
self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice");
|
||||
} else {
|
||||
after.push(self.lower_pat(pat));
|
||||
}
|
||||
}
|
||||
|
||||
hir::PatKind::Slice(before.into(), slice, after.into())
|
||||
}
|
||||
|
||||
fn lower_pat_ident(
|
||||
&mut self,
|
||||
p: &Pat,
|
||||
binding_mode: &BindingMode,
|
||||
ident: Ident,
|
||||
lower_sub: impl FnOnce(&mut Self) -> Option<P<hir::Pat>>,
|
||||
) -> hir::PatKind {
|
||||
match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
|
||||
// `None` can occur in body-less function signatures
|
||||
res @ None | res @ Some(Res::Local(_)) => {
|
||||
let canonical_id = match res {
|
||||
Some(Res::Local(id)) => id,
|
||||
_ => p.id,
|
||||
};
|
||||
|
||||
hir::PatKind::Binding(
|
||||
self.lower_binding_mode(binding_mode),
|
||||
self.lower_node_id(canonical_id),
|
||||
ident,
|
||||
lower_sub(self),
|
||||
)
|
||||
}
|
||||
Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
P(hir::Path {
|
||||
span: ident.span,
|
||||
res: self.lower_res(res),
|
||||
segments: hir_vec![hir::PathSegment::from_ident(ident)],
|
||||
}),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> P<hir::Pat> {
|
||||
self.pat_with_node_id_of(p, hir::PatKind::Wild)
|
||||
}
|
||||
|
||||
/// Construct a `Pat` with the `HirId` of `p.id` lowered.
|
||||
fn pat_with_node_id_of(&mut self, p: &Pat, node: hir::PatKind) -> P<hir::Pat> {
|
||||
P(hir::Pat {
|
||||
hir_id: self.lower_node_id(p.id),
|
||||
node,
|
||||
@ -4274,6 +4374,28 @@ impl<'a> LoweringContext<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
|
||||
fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
|
||||
self.diagnostic()
|
||||
.struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx))
|
||||
.span_label(sp, &format!("can only be used once per {} pattern", ctx))
|
||||
.span_label(prev_sp, "previously used here")
|
||||
.emit();
|
||||
}
|
||||
|
||||
/// Used to ban the `..` pattern in places it shouldn't be semantically.
|
||||
fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind {
|
||||
self.diagnostic()
|
||||
.struct_span_err(sp, "`..` patterns are not allowed here")
|
||||
.note("only allowed in tuple, tuple struct, and slice patterns")
|
||||
.emit();
|
||||
|
||||
// We're not in a list context so `..` can be reasonably treated
|
||||
// as `_` because it should always be valid and roughly matches the
|
||||
// intent of `..` (notice that the rest of a single slot is that slot).
|
||||
hir::PatKind::Wild
|
||||
}
|
||||
|
||||
fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
|
||||
match *e {
|
||||
RangeEnd::Included(_) => hir::RangeEnd::Included,
|
||||
|
@ -162,7 +162,7 @@ pub enum PatternKind<'tcx> {
|
||||
|
||||
/// Matches against a slice, checking the length and extracting elements.
|
||||
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
|
||||
/// e.g., `&[ref xs..]`.
|
||||
/// e.g., `&[ref xs @ ..]`.
|
||||
Slice {
|
||||
prefix: Vec<Pattern<'tcx>>,
|
||||
slice: Option<Pattern<'tcx>>,
|
||||
|
@ -287,7 +287,7 @@ impl<'a> AstValidator<'a> {
|
||||
// ```
|
||||
fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
|
||||
match expr.node {
|
||||
ExprKind::Lit(..) => {}
|
||||
ExprKind::Lit(..) | ExprKind::Err => {}
|
||||
ExprKind::Path(..) if allow_paths => {}
|
||||
ExprKind::Unary(UnOp::Neg, ref inner)
|
||||
if match inner.node { ExprKind::Lit(_) => true, _ => false } => {}
|
||||
|
@ -105,20 +105,34 @@ impl TargetDataLayout {
|
||||
let mut dl = TargetDataLayout::default();
|
||||
let mut i128_align_src = 64;
|
||||
for spec in target.data_layout.split('-') {
|
||||
match spec.split(':').collect::<Vec<_>>()[..] {
|
||||
let spec_parts = spec.split(':').collect::<Vec<_>>();
|
||||
|
||||
match &*spec_parts {
|
||||
["e"] => dl.endian = Endian::Little,
|
||||
["E"] => dl.endian = Endian::Big,
|
||||
[p] if p.starts_with("P") => {
|
||||
dl.instruction_address_space = parse_address_space(&p[1..], "P")?
|
||||
}
|
||||
["a", ref a..] => dl.aggregate_align = align(a, "a")?,
|
||||
["f32", ref a..] => dl.f32_align = align(a, "f32")?,
|
||||
["f64", ref a..] => dl.f64_align = align(a, "f64")?,
|
||||
[p @ "p", s, ref a..] | [p @ "p0", s, ref a..] => {
|
||||
// FIXME: Ping cfg(bootstrap) -- Use `ref a @ ..` with new bootstrap compiler.
|
||||
["a", ..] => {
|
||||
let a = &spec_parts[1..]; // FIXME inline into pattern.
|
||||
dl.aggregate_align = align(a, "a")?
|
||||
}
|
||||
["f32", ..] => {
|
||||
let a = &spec_parts[1..]; // FIXME inline into pattern.
|
||||
dl.f32_align = align(a, "f32")?
|
||||
}
|
||||
["f64", ..] => {
|
||||
let a = &spec_parts[1..]; // FIXME inline into pattern.
|
||||
dl.f64_align = align(a, "f64")?
|
||||
}
|
||||
[p @ "p", s, ..] | [p @ "p0", s, ..] => {
|
||||
let a = &spec_parts[2..]; // FIXME inline into pattern.
|
||||
dl.pointer_size = size(s, p)?;
|
||||
dl.pointer_align = align(a, p)?;
|
||||
}
|
||||
[s, ref a..] if s.starts_with("i") => {
|
||||
[s, ..] if s.starts_with("i") => {
|
||||
let a = &spec_parts[1..]; // FIXME inline into pattern.
|
||||
let bits = match s[1..].parse::<u64>() {
|
||||
Ok(bits) => bits,
|
||||
Err(_) => {
|
||||
@ -142,7 +156,8 @@ impl TargetDataLayout {
|
||||
dl.i128_align = a;
|
||||
}
|
||||
}
|
||||
[s, ref a..] if s.starts_with("v") => {
|
||||
[s, ..] if s.starts_with("v") => {
|
||||
let a = &spec_parts[1..]; // FIXME inline into pattern.
|
||||
let v_size = size(&s[1..], "v")?;
|
||||
let a = align(a, s)?;
|
||||
if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
|
||||
|
@ -196,7 +196,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let rhs_ty = self.check_expr(end);
|
||||
|
||||
// Check that both end-points are of numeric or char type.
|
||||
let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char();
|
||||
let numeric_or_char = |ty: Ty<'_>| {
|
||||
ty.is_numeric()
|
||||
|| ty.is_char()
|
||||
|| ty.references_error()
|
||||
};
|
||||
let lhs_compat = numeric_or_char(lhs_ty);
|
||||
let rhs_compat = numeric_or_char(rhs_ty);
|
||||
|
||||
|
@ -1818,7 +1818,9 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, d
|
||||
);
|
||||
let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg);
|
||||
err.span_label(sp, &msg);
|
||||
if let &[ref start.., ref end] = &variant_spans[..] {
|
||||
if let &[.., ref end] = &variant_spans[..] {
|
||||
// FIXME: Ping cfg(bootstrap) -- Use `ref start @ ..` with new bootstrap compiler.
|
||||
let start = &variant_spans[..variant_spans.len() - 1];
|
||||
for variant_span in start {
|
||||
err.span_label(*variant_span, "");
|
||||
}
|
||||
|
@ -3497,8 +3497,8 @@ Example of erroneous code:
|
||||
|
||||
let r = &[1, 2];
|
||||
match r {
|
||||
&[a, b, c, rest..] => { // error: pattern requires at least 3
|
||||
// elements but array has 2
|
||||
&[a, b, c, rest @ ..] => { // error: pattern requires at least 3
|
||||
// elements but array has 2
|
||||
println!("a={}, b={}, c={} rest={:?}", a, b, c, rest);
|
||||
}
|
||||
}
|
||||
@ -3512,7 +3512,7 @@ requires. You can match an arbitrary number of remaining elements with `..`:
|
||||
|
||||
let r = &[1, 2, 3, 4, 5];
|
||||
match r {
|
||||
&[a, b, c, rest..] => { // ok!
|
||||
&[a, b, c, rest @ ..] => { // ok!
|
||||
// prints `a=1, b=2, c=3 rest=[4, 5]`
|
||||
println!("a={}, b={}, c={} rest={:?}", a, b, c, rest);
|
||||
}
|
||||
|
@ -519,21 +519,28 @@ impl fmt::Debug for Pat {
|
||||
}
|
||||
|
||||
impl Pat {
|
||||
/// Attempt reparsing the pattern as a type.
|
||||
/// This is intended for use by diagnostics.
|
||||
pub(super) fn to_ty(&self) -> Option<P<Ty>> {
|
||||
let node = match &self.node {
|
||||
// In a type expression `_` is an inference variable.
|
||||
PatKind::Wild => TyKind::Infer,
|
||||
// An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
|
||||
PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) => {
|
||||
TyKind::Path(None, Path::from_ident(*ident))
|
||||
}
|
||||
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
|
||||
PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
|
||||
// `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type.
|
||||
PatKind::Ref(pat, mutbl) => pat
|
||||
.to_ty()
|
||||
.map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
|
||||
PatKind::Slice(pats, None, _) if pats.len() == 1 => {
|
||||
pats[0].to_ty().map(TyKind::Slice)?
|
||||
}
|
||||
PatKind::Tuple(pats, None) => {
|
||||
// A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
|
||||
// when `P` can be reparsed as a type `T`.
|
||||
PatKind::Slice(pats) if pats.len() == 1 => pats[0].to_ty().map(TyKind::Slice)?,
|
||||
// A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)`
|
||||
// assuming `T0` to `Tn` are all syntactically valid as types.
|
||||
PatKind::Tuple(pats) => {
|
||||
let mut tys = Vec::with_capacity(pats.len());
|
||||
// FIXME(#48994) - could just be collected into an Option<Vec>
|
||||
for pat in pats {
|
||||
@ -559,19 +566,15 @@ impl Pat {
|
||||
return false;
|
||||
}
|
||||
|
||||
match self.node {
|
||||
PatKind::Ident(_, _, Some(ref p)) => p.walk(it),
|
||||
PatKind::Struct(_, ref fields, _) => fields.iter().all(|field| field.node.pat.walk(it)),
|
||||
PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
|
||||
match &self.node {
|
||||
PatKind::Ident(_, _, Some(p)) => p.walk(it),
|
||||
PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.node.pat.walk(it)),
|
||||
PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) => {
|
||||
s.iter().all(|p| p.walk(it))
|
||||
}
|
||||
PatKind::Box(ref s) | PatKind::Ref(ref s, _) | PatKind::Paren(ref s) => s.walk(it),
|
||||
PatKind::Slice(ref before, ref slice, ref after) => {
|
||||
before.iter().all(|p| p.walk(it))
|
||||
&& slice.iter().all(|p| p.walk(it))
|
||||
&& after.iter().all(|p| p.walk(it))
|
||||
}
|
||||
PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it),
|
||||
PatKind::Wild
|
||||
| PatKind::Rest
|
||||
| PatKind::Lit(_)
|
||||
| PatKind::Range(..)
|
||||
| PatKind::Ident(..)
|
||||
@ -579,6 +582,14 @@ impl Pat {
|
||||
| PatKind::Mac(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Is this a `..` pattern?
|
||||
pub fn is_rest(&self) -> bool {
|
||||
match self.node {
|
||||
PatKind::Rest => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A single field in a struct pattern
|
||||
@ -630,9 +641,7 @@ pub enum PatKind {
|
||||
Struct(Path, Vec<Spanned<FieldPat>>, /* recovered */ bool),
|
||||
|
||||
/// 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>),
|
||||
TupleStruct(Path, Vec<P<Pat>>),
|
||||
|
||||
/// A possibly qualified path pattern.
|
||||
/// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
|
||||
@ -641,9 +650,7 @@ pub enum PatKind {
|
||||
Path(Option<QSelf>, Path),
|
||||
|
||||
/// 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>),
|
||||
Tuple(Vec<P<Pat>>),
|
||||
|
||||
/// A `box` pattern.
|
||||
Box(P<Pat>),
|
||||
@ -657,9 +664,22 @@ pub enum PatKind {
|
||||
/// A range pattern (e.g., `1...2`, `1..=2` or `1..2`).
|
||||
Range(P<Expr>, P<Expr>, Spanned<RangeEnd>),
|
||||
|
||||
/// `[a, b, ..i, y, z]` is represented as:
|
||||
/// `PatKind::Slice(box [a, b], Some(i), box [y, z])`
|
||||
Slice(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
|
||||
/// A slice pattern `[a, b, c]`.
|
||||
Slice(Vec<P<Pat>>),
|
||||
|
||||
/// A rest pattern `..`.
|
||||
///
|
||||
/// Syntactically it is valid anywhere.
|
||||
///
|
||||
/// Semantically however, it only has meaning immediately inside:
|
||||
/// - a slice pattern: `[a, .., b]`,
|
||||
/// - a binding pattern immediately inside a slice pattern: `[a, r @ ..]`,
|
||||
/// - a tuple pattern: `(a, .., b)`,
|
||||
/// - a tuple struct/variant pattern: `$path(a, .., b)`.
|
||||
///
|
||||
/// In all of these cases, an additional restriction applies,
|
||||
/// only one rest pattern may occur in the pattern sequences.
|
||||
Rest,
|
||||
|
||||
/// Parentheses in patterns used for grouping (i.e., `(PAT)`).
|
||||
Paren(P<Pat>),
|
||||
|
@ -840,14 +840,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
}
|
||||
fn pat_tuple_struct(&self, span: Span, path: ast::Path,
|
||||
subpats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
|
||||
self.pat(span, PatKind::TupleStruct(path, subpats, None))
|
||||
self.pat(span, PatKind::TupleStruct(path, subpats))
|
||||
}
|
||||
fn pat_struct(&self, span: Span, path: ast::Path,
|
||||
field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> {
|
||||
self.pat(span, PatKind::Struct(path, field_pats, false))
|
||||
}
|
||||
fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
|
||||
self.pat(span, PatKind::Tuple(pats, None))
|
||||
self.pat(span, PatKind::Tuple(pats))
|
||||
}
|
||||
|
||||
fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
|
||||
|
@ -2151,11 +2151,23 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pattern: &'a ast::Pat) {
|
||||
match pattern.node {
|
||||
PatKind::Slice(_, Some(ref subslice), _) => {
|
||||
gate_feature_post!(&self, slice_patterns,
|
||||
subslice.span,
|
||||
"syntax for subslices in slice patterns is not yet stabilized");
|
||||
match &pattern.node {
|
||||
PatKind::Slice(pats) => {
|
||||
for pat in &*pats {
|
||||
let span = pat.span;
|
||||
let inner_pat = match &pat.node {
|
||||
PatKind::Ident(.., Some(pat)) => pat,
|
||||
_ => pat,
|
||||
};
|
||||
if inner_pat.is_rest() {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
slice_patterns,
|
||||
span,
|
||||
"subslice patterns are unstable"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
PatKind::Box(..) => {
|
||||
gate_feature_post!(&self, box_patterns,
|
||||
|
@ -1020,15 +1020,15 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
|
||||
let Pat { id, node, span } = pat.deref_mut();
|
||||
vis.visit_id(id);
|
||||
match node {
|
||||
PatKind::Wild => {}
|
||||
PatKind::Wild | PatKind::Rest => {}
|
||||
PatKind::Ident(_binding_mode, ident, sub) => {
|
||||
vis.visit_ident(ident);
|
||||
visit_opt(sub, |sub| vis.visit_pat(sub));
|
||||
}
|
||||
PatKind::Lit(e) => vis.visit_expr(e),
|
||||
PatKind::TupleStruct(path, pats, _ddpos) => {
|
||||
PatKind::TupleStruct(path, elems) => {
|
||||
vis.visit_path(path);
|
||||
visit_vec(pats, |pat| vis.visit_pat(pat));
|
||||
visit_vec(elems, |elem| vis.visit_pat(elem));
|
||||
}
|
||||
PatKind::Path(qself, path) => {
|
||||
vis.visit_qself(qself);
|
||||
@ -1043,7 +1043,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
|
||||
vis.visit_span(span);
|
||||
};
|
||||
}
|
||||
PatKind::Tuple(elts, _ddpos) => visit_vec(elts, |elt| vis.visit_pat(elt)),
|
||||
PatKind::Tuple(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)),
|
||||
PatKind::Box(inner) => vis.visit_pat(inner),
|
||||
PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
|
||||
PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
|
||||
@ -1051,11 +1051,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
|
||||
vis.visit_expr(e2);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
PatKind::Slice(before, slice, after) => {
|
||||
visit_vec(before, |pat| vis.visit_pat(pat));
|
||||
visit_opt(slice, |slice| vis.visit_pat(slice));
|
||||
visit_vec(after, |pat| vis.visit_pat(pat));
|
||||
}
|
||||
PatKind::Slice(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)),
|
||||
PatKind::Paren(inner) => vis.visit_pat(inner),
|
||||
PatKind::Mac(mac) => vis.visit_mac(mac),
|
||||
}
|
||||
|
@ -890,14 +890,13 @@ impl<'a> Parser<'a> {
|
||||
/// Parses a sequence, including the closing delimiter. The function
|
||||
/// `f` must consume tokens until reaching the next separator or
|
||||
/// closing bracket.
|
||||
pub fn parse_seq_to_end<T, F>(&mut self,
|
||||
ket: &TokenKind,
|
||||
sep: SeqSep,
|
||||
f: F)
|
||||
-> PResult<'a, Vec<T>> where
|
||||
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
{
|
||||
let (val, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
|
||||
pub fn parse_seq_to_end<T>(
|
||||
&mut self,
|
||||
ket: &TokenKind,
|
||||
sep: SeqSep,
|
||||
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
) -> PResult<'a, Vec<T>> {
|
||||
let (val, _, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
|
||||
if !recovered {
|
||||
self.bump();
|
||||
}
|
||||
@ -907,39 +906,39 @@ impl<'a> Parser<'a> {
|
||||
/// Parses a sequence, not including the closing delimiter. The function
|
||||
/// `f` must consume tokens until reaching the next separator or
|
||||
/// closing bracket.
|
||||
pub fn parse_seq_to_before_end<T, F>(
|
||||
pub fn parse_seq_to_before_end<T>(
|
||||
&mut self,
|
||||
ket: &TokenKind,
|
||||
sep: SeqSep,
|
||||
f: F,
|
||||
) -> PResult<'a, (Vec<T>, bool)>
|
||||
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
|
||||
{
|
||||
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
) -> PResult<'a, (Vec<T>, bool, bool)> {
|
||||
self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
|
||||
}
|
||||
|
||||
crate fn parse_seq_to_before_tokens<T, F>(
|
||||
fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType) -> bool {
|
||||
kets.iter().any(|k| {
|
||||
match expect {
|
||||
TokenExpectType::Expect => self.check(k),
|
||||
TokenExpectType::NoExpect => self.token == **k,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
crate fn parse_seq_to_before_tokens<T>(
|
||||
&mut self,
|
||||
kets: &[&TokenKind],
|
||||
sep: SeqSep,
|
||||
expect: TokenExpectType,
|
||||
mut f: F,
|
||||
) -> PResult<'a, (Vec<T>, bool /* recovered */)>
|
||||
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
|
||||
{
|
||||
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
) -> PResult<'a, (Vec<T>, bool /* trailing */, bool /* recovered */)> {
|
||||
let mut first = true;
|
||||
let mut recovered = false;
|
||||
let mut trailing = false;
|
||||
let mut v = vec![];
|
||||
while !kets.iter().any(|k| {
|
||||
match expect {
|
||||
TokenExpectType::Expect => self.check(k),
|
||||
TokenExpectType::NoExpect => self.token == **k,
|
||||
}
|
||||
}) {
|
||||
match self.token.kind {
|
||||
token::CloseDelim(..) | token::Eof => break,
|
||||
_ => {}
|
||||
};
|
||||
while !self.expect_any_with_type(kets, expect) {
|
||||
if let token::CloseDelim(..) | token::Eof = self.token.kind {
|
||||
break
|
||||
}
|
||||
if let Some(ref t) = sep.sep {
|
||||
if first {
|
||||
first = false;
|
||||
@ -973,12 +972,8 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if sep.trailing_sep_allowed && kets.iter().any(|k| {
|
||||
match expect {
|
||||
TokenExpectType::Expect => self.check(k),
|
||||
TokenExpectType::NoExpect => self.token == **k,
|
||||
}
|
||||
}) {
|
||||
if sep.trailing_sep_allowed && self.expect_any_with_type(kets, expect) {
|
||||
trailing = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -986,27 +981,45 @@ impl<'a> Parser<'a> {
|
||||
v.push(t);
|
||||
}
|
||||
|
||||
Ok((v, recovered))
|
||||
Ok((v, trailing, recovered))
|
||||
}
|
||||
|
||||
/// Parses a sequence, including the closing delimiter. The function
|
||||
/// `f` must consume tokens until reaching the next separator or
|
||||
/// closing bracket.
|
||||
fn parse_unspanned_seq<T, F>(
|
||||
fn parse_unspanned_seq<T>(
|
||||
&mut self,
|
||||
bra: &TokenKind,
|
||||
ket: &TokenKind,
|
||||
sep: SeqSep,
|
||||
f: F,
|
||||
) -> PResult<'a, Vec<T>> where
|
||||
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
{
|
||||
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
) -> PResult<'a, (Vec<T>, bool)> {
|
||||
self.expect(bra)?;
|
||||
let (result, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
|
||||
let (result, trailing, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
|
||||
if !recovered {
|
||||
self.eat(ket);
|
||||
}
|
||||
Ok(result)
|
||||
Ok((result, trailing))
|
||||
}
|
||||
|
||||
fn parse_delim_comma_seq<T>(
|
||||
&mut self,
|
||||
delim: DelimToken,
|
||||
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
) -> PResult<'a, (Vec<T>, bool)> {
|
||||
self.parse_unspanned_seq(
|
||||
&token::OpenDelim(delim),
|
||||
&token::CloseDelim(delim),
|
||||
SeqSep::trailing_allowed(token::Comma),
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_paren_comma_seq<T>(
|
||||
&mut self,
|
||||
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
) -> PResult<'a, (Vec<T>, bool)> {
|
||||
self.parse_delim_comma_seq(token::Paren, f)
|
||||
}
|
||||
|
||||
/// Advance the parser by one token
|
||||
@ -1804,15 +1817,7 @@ impl<'a> Parser<'a> {
|
||||
AngleBracketedArgs { args, constraints, span }.into()
|
||||
} else {
|
||||
// `(T, U) -> R`
|
||||
self.bump(); // `(`
|
||||
let (inputs, recovered) = self.parse_seq_to_before_tokens(
|
||||
&[&token::CloseDelim(token::Paren)],
|
||||
SeqSep::trailing_allowed(token::Comma),
|
||||
TokenExpectType::Expect,
|
||||
|p| p.parse_ty())?;
|
||||
if !recovered {
|
||||
self.bump(); // `)`
|
||||
}
|
||||
let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
|
||||
let span = lo.to(self.prev_span);
|
||||
let output = if self.eat(&token::RArrow) {
|
||||
Some(self.parse_ty_common(false, false, false)?)
|
||||
@ -2516,12 +2521,7 @@ impl<'a> Parser<'a> {
|
||||
Ok(match self.token.kind {
|
||||
token::OpenDelim(token::Paren) => {
|
||||
// Method call `expr.f()`
|
||||
let mut args = self.parse_unspanned_seq(
|
||||
&token::OpenDelim(token::Paren),
|
||||
&token::CloseDelim(token::Paren),
|
||||
SeqSep::trailing_allowed(token::Comma),
|
||||
|p| Ok(p.parse_expr()?)
|
||||
)?;
|
||||
let mut args = self.parse_paren_expr_seq()?;
|
||||
args.insert(0, self_arg);
|
||||
|
||||
let span = lo.to(self.prev_span);
|
||||
@ -2606,12 +2606,7 @@ impl<'a> Parser<'a> {
|
||||
match self.token.kind {
|
||||
// expr(...)
|
||||
token::OpenDelim(token::Paren) => {
|
||||
let seq = self.parse_unspanned_seq(
|
||||
&token::OpenDelim(token::Paren),
|
||||
&token::CloseDelim(token::Paren),
|
||||
SeqSep::trailing_allowed(token::Comma),
|
||||
|p| Ok(p.parse_expr()?)
|
||||
).map(|es| {
|
||||
let seq = self.parse_paren_expr_seq().map(|es| {
|
||||
let nd = self.mk_call(e, es);
|
||||
let hi = self.prev_span;
|
||||
self.mk_expr(lo.to(hi), nd, ThinVec::new())
|
||||
@ -2635,6 +2630,10 @@ impl<'a> Parser<'a> {
|
||||
return Ok(e);
|
||||
}
|
||||
|
||||
fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec<P<Expr>>> {
|
||||
self.parse_paren_comma_seq(|p| p.parse_expr()).map(|(r, _)| r)
|
||||
}
|
||||
|
||||
crate fn process_potential_macro_variable(&mut self) {
|
||||
self.token = match self.token.kind {
|
||||
token::Dollar if self.token.span.ctxt() != SyntaxContext::empty() &&
|
||||
@ -3536,122 +3535,6 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
}
|
||||
|
||||
// Parses a parenthesized list of patterns like
|
||||
// `()`, `(p)`, `(p,)`, `(p, q)`, or `(p, .., q)`. Returns:
|
||||
// - a vector of the patterns that were parsed
|
||||
// - an option indicating the index of the `..` element
|
||||
// - a boolean indicating whether a trailing comma was present.
|
||||
// Trailing commas are significant because (p) and (p,) are different patterns.
|
||||
fn parse_parenthesized_pat_list(&mut self) -> PResult<'a, (Vec<P<Pat>>, Option<usize>, bool)> {
|
||||
self.expect(&token::OpenDelim(token::Paren))?;
|
||||
let result = match self.parse_pat_list() {
|
||||
Ok(result) => result,
|
||||
Err(mut err) => { // recover from parse error in tuple pattern list
|
||||
err.emit();
|
||||
self.consume_block(token::Paren);
|
||||
return Ok((vec![], Some(0), false));
|
||||
}
|
||||
};
|
||||
self.expect(&token::CloseDelim(token::Paren))?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn parse_pat_list(&mut self) -> PResult<'a, (Vec<P<Pat>>, Option<usize>, bool)> {
|
||||
let mut fields = Vec::new();
|
||||
let mut ddpos = None;
|
||||
let mut prev_dd_sp = None;
|
||||
let mut trailing_comma = false;
|
||||
loop {
|
||||
if self.eat(&token::DotDot) {
|
||||
if ddpos.is_none() {
|
||||
ddpos = Some(fields.len());
|
||||
prev_dd_sp = Some(self.prev_span);
|
||||
} else {
|
||||
// Emit a friendly error, ignore `..` and continue parsing
|
||||
let mut err = self.struct_span_err(
|
||||
self.prev_span,
|
||||
"`..` can only be used once per tuple or tuple struct pattern",
|
||||
);
|
||||
err.span_label(self.prev_span, "can only be used once per pattern");
|
||||
if let Some(sp) = prev_dd_sp {
|
||||
err.span_label(sp, "previously present here");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
} else if !self.check(&token::CloseDelim(token::Paren)) {
|
||||
fields.push(self.parse_pat(None)?);
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
trailing_comma = self.eat(&token::Comma);
|
||||
if !trailing_comma {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if ddpos == Some(fields.len()) && trailing_comma {
|
||||
// `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
|
||||
let msg = "trailing comma is not permitted after `..`";
|
||||
self.struct_span_err(self.prev_span, msg)
|
||||
.span_label(self.prev_span, msg)
|
||||
.emit();
|
||||
}
|
||||
|
||||
Ok((fields, ddpos, trailing_comma))
|
||||
}
|
||||
|
||||
fn parse_pat_vec_elements(
|
||||
&mut self,
|
||||
) -> PResult<'a, (Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>)> {
|
||||
let mut before = Vec::new();
|
||||
let mut slice = None;
|
||||
let mut after = Vec::new();
|
||||
let mut first = true;
|
||||
let mut before_slice = true;
|
||||
|
||||
while self.token != token::CloseDelim(token::Bracket) {
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
self.expect(&token::Comma)?;
|
||||
|
||||
if self.token == token::CloseDelim(token::Bracket)
|
||||
&& (before_slice || !after.is_empty()) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if before_slice {
|
||||
if self.eat(&token::DotDot) {
|
||||
|
||||
if self.check(&token::Comma) ||
|
||||
self.check(&token::CloseDelim(token::Bracket)) {
|
||||
slice = Some(P(Pat {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
node: PatKind::Wild,
|
||||
span: self.prev_span,
|
||||
}));
|
||||
before_slice = false;
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
let subpat = self.parse_pat(None)?;
|
||||
if before_slice && self.eat(&token::DotDot) {
|
||||
slice = Some(subpat);
|
||||
before_slice = false;
|
||||
} else if before_slice {
|
||||
before.push(subpat);
|
||||
} else {
|
||||
after.push(subpat);
|
||||
}
|
||||
}
|
||||
|
||||
Ok((before, slice, after))
|
||||
}
|
||||
|
||||
fn parse_pat_field(
|
||||
&mut self,
|
||||
lo: Span,
|
||||
@ -3847,20 +3730,34 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// helper function to decide whether to parse as ident binding or to try to do
|
||||
// something more complex like range patterns
|
||||
/// Is the current token suitable as the start of a range patterns end?
|
||||
fn is_pat_range_end_start(&self) -> bool {
|
||||
self.token.is_path_start() // e.g. `MY_CONST`;
|
||||
|| self.token == token::Dot // e.g. `.5` for recovery;
|
||||
|| self.token.can_begin_literal_or_bool() // e.g. `42`.
|
||||
}
|
||||
|
||||
// Helper function to decide whether to parse as ident binding
|
||||
// or to try to do something more complex like range patterns.
|
||||
fn parse_as_ident(&mut self) -> bool {
|
||||
self.look_ahead(1, |t| match t.kind {
|
||||
token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
|
||||
token::DotDotDot | token::DotDotEq | token::ModSep | token::Not => Some(false),
|
||||
// ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the
|
||||
// range pattern branch
|
||||
token::DotDot => None,
|
||||
_ => Some(true),
|
||||
}).unwrap_or_else(|| self.look_ahead(2, |t| match t.kind {
|
||||
token::Comma | token::CloseDelim(token::Bracket) => true,
|
||||
_ => false,
|
||||
}))
|
||||
token::DotDotDot | token::DotDotEq | token::DotDot |
|
||||
token::ModSep | token::Not => false,
|
||||
_ => true,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse and throw away a parentesized comma separated
|
||||
/// sequence of patterns until `)` is reached.
|
||||
fn skip_pat_list(&mut self) -> PResult<'a, ()> {
|
||||
while !self.check(&token::CloseDelim(token::Paren)) {
|
||||
self.parse_pat(None)?;
|
||||
if !self.eat(&token::Comma) {
|
||||
return Ok(())
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A wrapper around `parse_pat` with some special error handling for the
|
||||
@ -3876,7 +3773,7 @@ impl<'a> Parser<'a> {
|
||||
// later.
|
||||
let comma_span = self.token.span;
|
||||
self.bump();
|
||||
if let Err(mut err) = self.parse_pat_list() {
|
||||
if let Err(mut err) = self.skip_pat_list() {
|
||||
// We didn't expect this to work anyway; we just wanted
|
||||
// to advance to the end of the comma-sequence so we know
|
||||
// the span to suggest parenthesizing
|
||||
@ -3908,6 +3805,53 @@ impl<'a> Parser<'a> {
|
||||
self.parse_pat_with_range_pat(true, expected)
|
||||
}
|
||||
|
||||
/// Parse a range-to pattern, e.g. `..X` and `..=X` for recovery.
|
||||
fn parse_pat_range_to(&mut self, re: RangeEnd, form: &str) -> PResult<'a, PatKind> {
|
||||
let lo = self.prev_span;
|
||||
let end = self.parse_pat_range_end()?;
|
||||
let range_span = lo.to(end.span);
|
||||
let begin = self.mk_expr(range_span, ExprKind::Err, ThinVec::new());
|
||||
|
||||
self.diagnostic()
|
||||
.struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
|
||||
.span_suggestion(
|
||||
range_span,
|
||||
"try using the minimum value for the type",
|
||||
format!("MIN{}{}", form, pprust::expr_to_string(&end)),
|
||||
Applicability::HasPlaceholders,
|
||||
)
|
||||
.emit();
|
||||
|
||||
Ok(PatKind::Range(begin, end, respan(lo, re)))
|
||||
}
|
||||
|
||||
/// Parse the end of a `X..Y`, `X..=Y`, or `X...Y` range pattern or recover
|
||||
/// if that end is missing treating it as `X..`, `X..=`, or `X...` respectively.
|
||||
fn parse_pat_range_end_opt(&mut self, begin: &Expr, form: &str) -> PResult<'a, P<Expr>> {
|
||||
if self.is_pat_range_end_start() {
|
||||
// Parsing e.g. `X..=Y`.
|
||||
self.parse_pat_range_end()
|
||||
} else {
|
||||
// Parsing e.g. `X..`.
|
||||
let range_span = begin.span.to(self.prev_span);
|
||||
|
||||
self.diagnostic()
|
||||
.struct_span_err(
|
||||
range_span,
|
||||
&format!("`X{}` range patterns are not supported", form),
|
||||
)
|
||||
.span_suggestion(
|
||||
range_span,
|
||||
"try using the maximum value for the type",
|
||||
format!("{}{}MAX", pprust::expr_to_string(&begin), form),
|
||||
Applicability::HasPlaceholders,
|
||||
)
|
||||
.emit();
|
||||
|
||||
Ok(self.mk_expr(range_span, ExprKind::Err, ThinVec::new()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
|
||||
/// allowed).
|
||||
fn parse_pat_with_range_pat(
|
||||
@ -3934,20 +3878,41 @@ impl<'a> Parser<'a> {
|
||||
pat = PatKind::Ref(subpat, mutbl);
|
||||
}
|
||||
token::OpenDelim(token::Paren) => {
|
||||
// Parse (pat,pat,pat,...) as tuple pattern
|
||||
let (fields, ddpos, trailing_comma) = self.parse_parenthesized_pat_list()?;
|
||||
pat = if fields.len() == 1 && ddpos.is_none() && !trailing_comma {
|
||||
// Parse a tuple or parenthesis pattern.
|
||||
let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
|
||||
|
||||
// Here, `(pat,)` is a tuple pattern.
|
||||
// For backward compatibility, `(..)` is a tuple pattern as well.
|
||||
pat = if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) {
|
||||
PatKind::Paren(fields.into_iter().nth(0).unwrap())
|
||||
} else {
|
||||
PatKind::Tuple(fields, ddpos)
|
||||
PatKind::Tuple(fields)
|
||||
};
|
||||
}
|
||||
token::OpenDelim(token::Bracket) => {
|
||||
// Parse [pat,pat,...] as slice pattern
|
||||
// Parse `[pat, pat,...]` as a slice pattern.
|
||||
let (slice, _) = self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?;
|
||||
pat = PatKind::Slice(slice);
|
||||
}
|
||||
token::DotDot => {
|
||||
self.bump();
|
||||
let (before, slice, after) = self.parse_pat_vec_elements()?;
|
||||
self.expect(&token::CloseDelim(token::Bracket))?;
|
||||
pat = PatKind::Slice(before, slice, after);
|
||||
pat = if self.is_pat_range_end_start() {
|
||||
// Parse `..42` for recovery.
|
||||
self.parse_pat_range_to(RangeEnd::Excluded, "..")?
|
||||
} else {
|
||||
// A rest pattern `..`.
|
||||
PatKind::Rest
|
||||
};
|
||||
}
|
||||
token::DotDotEq => {
|
||||
// Parse `..=42` for recovery.
|
||||
self.bump();
|
||||
pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?;
|
||||
}
|
||||
token::DotDotDot => {
|
||||
// Parse `...42` for recovery.
|
||||
self.bump();
|
||||
pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?;
|
||||
}
|
||||
// At this point, token != &, &&, (, [
|
||||
_ => if self.eat_keyword(kw::Underscore) {
|
||||
@ -4004,10 +3969,10 @@ impl<'a> Parser<'a> {
|
||||
pat = PatKind::Mac(mac);
|
||||
}
|
||||
token::DotDotDot | token::DotDotEq | token::DotDot => {
|
||||
let end_kind = match self.token.kind {
|
||||
token::DotDot => RangeEnd::Excluded,
|
||||
token::DotDotDot => RangeEnd::Included(RangeSyntax::DotDotDot),
|
||||
token::DotDotEq => RangeEnd::Included(RangeSyntax::DotDotEq),
|
||||
let (end_kind, form) = match self.token.kind {
|
||||
token::DotDot => (RangeEnd::Excluded, ".."),
|
||||
token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."),
|
||||
token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="),
|
||||
_ => panic!("can only parse `..`/`...`/`..=` for ranges \
|
||||
(checked above)"),
|
||||
};
|
||||
@ -4016,9 +3981,8 @@ impl<'a> Parser<'a> {
|
||||
let span = lo.to(self.prev_span);
|
||||
let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new());
|
||||
self.bump();
|
||||
let end = self.parse_pat_range_end()?;
|
||||
let op = Spanned { span: op_span, node: end_kind };
|
||||
pat = PatKind::Range(begin, end, op);
|
||||
let end = self.parse_pat_range_end_opt(&begin, form)?;
|
||||
pat = PatKind::Range(begin, end, respan(op_span, end_kind));
|
||||
}
|
||||
token::OpenDelim(token::Brace) => {
|
||||
if qself.is_some() {
|
||||
@ -4045,8 +4009,8 @@ impl<'a> Parser<'a> {
|
||||
return Err(err);
|
||||
}
|
||||
// Parse tuple struct or enum pattern
|
||||
let (fields, ddpos, _) = self.parse_parenthesized_pat_list()?;
|
||||
pat = PatKind::TupleStruct(path, fields, ddpos)
|
||||
let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
|
||||
pat = PatKind::TupleStruct(path, fields)
|
||||
}
|
||||
_ => pat = PatKind::Path(qself, path),
|
||||
}
|
||||
@ -4057,19 +4021,18 @@ impl<'a> Parser<'a> {
|
||||
let op_span = self.token.span;
|
||||
if self.check(&token::DotDot) || self.check(&token::DotDotEq) ||
|
||||
self.check(&token::DotDotDot) {
|
||||
let end_kind = if self.eat(&token::DotDotDot) {
|
||||
RangeEnd::Included(RangeSyntax::DotDotDot)
|
||||
let (end_kind, form) = if self.eat(&token::DotDotDot) {
|
||||
(RangeEnd::Included(RangeSyntax::DotDotDot), "...")
|
||||
} else if self.eat(&token::DotDotEq) {
|
||||
RangeEnd::Included(RangeSyntax::DotDotEq)
|
||||
(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")
|
||||
} else if self.eat(&token::DotDot) {
|
||||
RangeEnd::Excluded
|
||||
(RangeEnd::Excluded, "..")
|
||||
} else {
|
||||
panic!("impossible case: we already matched \
|
||||
on a range-operator token")
|
||||
};
|
||||
let end = self.parse_pat_range_end()?;
|
||||
let op = Spanned { span: op_span, node: end_kind };
|
||||
pat = PatKind::Range(begin, end, op);
|
||||
let end = self.parse_pat_range_end_opt(&begin, form)?;
|
||||
pat = PatKind::Range(begin, end, respan(op_span, end_kind))
|
||||
} else {
|
||||
pat = PatKind::Lit(begin);
|
||||
}
|
||||
@ -5359,59 +5322,48 @@ impl<'a> Parser<'a> {
|
||||
|
||||
fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool)
|
||||
-> PResult<'a, (Vec<Arg> , bool)> {
|
||||
self.expect(&token::OpenDelim(token::Paren))?;
|
||||
|
||||
let sp = self.token.span;
|
||||
let mut c_variadic = false;
|
||||
let (args, recovered): (Vec<Option<Arg>>, bool) =
|
||||
self.parse_seq_to_before_end(
|
||||
&token::CloseDelim(token::Paren),
|
||||
SeqSep::trailing_allowed(token::Comma),
|
||||
|p| {
|
||||
let do_not_enforce_named_arguments_for_c_variadic =
|
||||
|token: &token::Token| -> bool {
|
||||
if token == &token::DotDotDot {
|
||||
false
|
||||
} else {
|
||||
named_args
|
||||
}
|
||||
};
|
||||
match p.parse_arg_general(
|
||||
false,
|
||||
allow_c_variadic,
|
||||
do_not_enforce_named_arguments_for_c_variadic
|
||||
) {
|
||||
Ok(arg) => {
|
||||
if let TyKind::CVarArgs = arg.ty.node {
|
||||
c_variadic = true;
|
||||
if p.token != token::CloseDelim(token::Paren) {
|
||||
let span = p.token.span;
|
||||
p.span_err(span,
|
||||
"`...` must be the last argument of a C-variadic function");
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(arg))
|
||||
}
|
||||
} else {
|
||||
Ok(Some(arg))
|
||||
}
|
||||
},
|
||||
Err(mut e) => {
|
||||
e.emit();
|
||||
let lo = p.prev_span;
|
||||
// Skip every token until next possible arg or end.
|
||||
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
|
||||
// Create a placeholder argument for proper arg count (issue #34264).
|
||||
let span = lo.to(p.prev_span);
|
||||
Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
|
||||
}
|
||||
let (args, _): (Vec<Option<Arg>>, _) = self.parse_paren_comma_seq(|p| {
|
||||
let do_not_enforce_named_arguments_for_c_variadic =
|
||||
|token: &token::Token| -> bool {
|
||||
if token == &token::DotDotDot {
|
||||
false
|
||||
} else {
|
||||
named_args
|
||||
}
|
||||
};
|
||||
match p.parse_arg_general(
|
||||
false,
|
||||
allow_c_variadic,
|
||||
do_not_enforce_named_arguments_for_c_variadic
|
||||
) {
|
||||
Ok(arg) => {
|
||||
if let TyKind::CVarArgs = arg.ty.node {
|
||||
c_variadic = true;
|
||||
if p.token != token::CloseDelim(token::Paren) {
|
||||
let span = p.token.span;
|
||||
p.span_err(span,
|
||||
"`...` must be the last argument of a C-variadic function");
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(arg))
|
||||
}
|
||||
} else {
|
||||
Ok(Some(arg))
|
||||
}
|
||||
},
|
||||
Err(mut e) => {
|
||||
e.emit();
|
||||
let lo = p.prev_span;
|
||||
// Skip every token until next possible arg or end.
|
||||
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
|
||||
// Create a placeholder argument for proper arg count (issue #34264).
|
||||
let span = lo.to(p.prev_span);
|
||||
Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
|
||||
}
|
||||
)?;
|
||||
|
||||
if !recovered {
|
||||
self.eat(&token::CloseDelim(token::Paren));
|
||||
}
|
||||
}
|
||||
})?;
|
||||
|
||||
let args: Vec<_> = args.into_iter().filter_map(|x| x).collect();
|
||||
|
||||
@ -5573,7 +5525,7 @@ impl<'a> Parser<'a> {
|
||||
(vec![self_arg], false)
|
||||
} else if self.eat(&token::Comma) {
|
||||
let mut fn_inputs = vec![self_arg];
|
||||
let (mut input, recovered) = self.parse_seq_to_before_end(
|
||||
let (mut input, _, recovered) = self.parse_seq_to_before_end(
|
||||
&token::CloseDelim(token::Paren), sep, parse_arg_fn)?;
|
||||
fn_inputs.append(&mut input);
|
||||
(fn_inputs, recovered)
|
||||
@ -5584,7 +5536,9 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?
|
||||
let (input, _, recovered) =
|
||||
self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?;
|
||||
(input, recovered)
|
||||
};
|
||||
|
||||
if !recovered {
|
||||
@ -6185,26 +6139,20 @@ impl<'a> Parser<'a> {
|
||||
fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
|
||||
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
|
||||
// Unit like structs are handled in parse_item_struct function
|
||||
let fields = self.parse_unspanned_seq(
|
||||
&token::OpenDelim(token::Paren),
|
||||
&token::CloseDelim(token::Paren),
|
||||
SeqSep::trailing_allowed(token::Comma),
|
||||
|p| {
|
||||
let attrs = p.parse_outer_attributes()?;
|
||||
let lo = p.token.span;
|
||||
let vis = p.parse_visibility(true)?;
|
||||
let ty = p.parse_ty()?;
|
||||
Ok(StructField {
|
||||
span: lo.to(ty.span),
|
||||
vis,
|
||||
ident: None,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
ty,
|
||||
attrs,
|
||||
})
|
||||
})?;
|
||||
|
||||
Ok(fields)
|
||||
self.parse_paren_comma_seq(|p| {
|
||||
let attrs = p.parse_outer_attributes()?;
|
||||
let lo = p.token.span;
|
||||
let vis = p.parse_visibility(true)?;
|
||||
let ty = p.parse_ty()?;
|
||||
Ok(StructField {
|
||||
span: lo.to(ty.span),
|
||||
vis,
|
||||
ident: None,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
ty,
|
||||
attrs,
|
||||
})
|
||||
}).map(|(r, _)| r)
|
||||
}
|
||||
|
||||
/// Parses a structure field declaration.
|
||||
@ -7786,11 +7734,8 @@ impl<'a> Parser<'a> {
|
||||
/// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`]
|
||||
/// ```
|
||||
fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
|
||||
self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
|
||||
&token::CloseDelim(token::Brace),
|
||||
SeqSep::trailing_allowed(token::Comma), |this| {
|
||||
Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID))
|
||||
})
|
||||
self.parse_delim_comma_seq(token::Brace, |p| Ok((p.parse_use_tree()?, ast::DUMMY_NODE_ID)))
|
||||
.map(|(r, _)| r)
|
||||
}
|
||||
|
||||
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
|
||||
|
@ -2368,22 +2368,10 @@ impl<'a> State<'a> {
|
||||
self.print_pat(p);
|
||||
}
|
||||
}
|
||||
PatKind::TupleStruct(ref path, ref elts, ddpos) => {
|
||||
PatKind::TupleStruct(ref path, ref elts) => {
|
||||
self.print_path(path, true, 0);
|
||||
self.popen();
|
||||
if let Some(ddpos) = ddpos {
|
||||
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
|
||||
if ddpos != 0 {
|
||||
self.word_space(",");
|
||||
}
|
||||
self.s.word("..");
|
||||
if ddpos != elts.len() {
|
||||
self.s.word(",");
|
||||
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p));
|
||||
}
|
||||
} else {
|
||||
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
|
||||
}
|
||||
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
|
||||
self.pclose();
|
||||
}
|
||||
PatKind::Path(None, ref path) => {
|
||||
@ -2415,23 +2403,11 @@ impl<'a> State<'a> {
|
||||
self.s.space();
|
||||
self.s.word("}");
|
||||
}
|
||||
PatKind::Tuple(ref elts, ddpos) => {
|
||||
PatKind::Tuple(ref elts) => {
|
||||
self.popen();
|
||||
if let Some(ddpos) = ddpos {
|
||||
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
|
||||
if ddpos != 0 {
|
||||
self.word_space(",");
|
||||
}
|
||||
self.s.word("..");
|
||||
if ddpos != elts.len() {
|
||||
self.s.word(",");
|
||||
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 {
|
||||
self.s.word(",");
|
||||
}
|
||||
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
|
||||
if elts.len() == 1 {
|
||||
self.s.word(",");
|
||||
}
|
||||
self.pclose();
|
||||
}
|
||||
@ -2457,26 +2433,12 @@ impl<'a> State<'a> {
|
||||
}
|
||||
self.print_expr(end);
|
||||
}
|
||||
PatKind::Slice(ref before, ref slice, ref after) => {
|
||||
PatKind::Slice(ref elts) => {
|
||||
self.s.word("[");
|
||||
self.commasep(Inconsistent,
|
||||
&before[..],
|
||||
|s, p| s.print_pat(p));
|
||||
if let Some(ref p) = *slice {
|
||||
if !before.is_empty() { self.word_space(","); }
|
||||
if let PatKind::Wild = p.node {
|
||||
// Print nothing
|
||||
} else {
|
||||
self.print_pat(p);
|
||||
}
|
||||
self.s.word("..");
|
||||
if !after.is_empty() { self.word_space(","); }
|
||||
}
|
||||
self.commasep(Inconsistent,
|
||||
&after[..],
|
||||
|s, p| s.print_pat(p));
|
||||
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
|
||||
self.s.word("]");
|
||||
}
|
||||
PatKind::Rest => self.s.word(".."),
|
||||
PatKind::Paren(ref inner) => {
|
||||
self.popen();
|
||||
self.print_pat(inner);
|
||||
|
@ -428,9 +428,9 @@ pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(visitor: &mut V,
|
||||
|
||||
pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
|
||||
match pattern.node {
|
||||
PatKind::TupleStruct(ref path, ref children, _) => {
|
||||
PatKind::TupleStruct(ref path, ref elems) => {
|
||||
visitor.visit_path(path, pattern.id);
|
||||
walk_list!(visitor, visit_pat, children);
|
||||
walk_list!(visitor, visit_pat, elems);
|
||||
}
|
||||
PatKind::Path(ref opt_qself, ref path) => {
|
||||
if let Some(ref qself) = *opt_qself {
|
||||
@ -446,8 +446,8 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
|
||||
visitor.visit_pat(&field.node.pat)
|
||||
}
|
||||
}
|
||||
PatKind::Tuple(ref tuple_elements, _) => {
|
||||
walk_list!(visitor, visit_pat, tuple_elements);
|
||||
PatKind::Tuple(ref elems) => {
|
||||
walk_list!(visitor, visit_pat, elems);
|
||||
}
|
||||
PatKind::Box(ref subpattern) |
|
||||
PatKind::Ref(ref subpattern, _) |
|
||||
@ -463,11 +463,9 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
|
||||
visitor.visit_expr(lower_bound);
|
||||
visitor.visit_expr(upper_bound);
|
||||
}
|
||||
PatKind::Wild => (),
|
||||
PatKind::Slice(ref prepatterns, ref slice_pattern, ref postpatterns) => {
|
||||
walk_list!(visitor, visit_pat, prepatterns);
|
||||
walk_list!(visitor, visit_pat, slice_pattern);
|
||||
walk_list!(visitor, visit_pat, postpatterns);
|
||||
PatKind::Wild | PatKind::Rest => {},
|
||||
PatKind::Slice(ref elems) => {
|
||||
walk_list!(visitor, visit_pat, elems);
|
||||
}
|
||||
PatKind::Mac(ref mac) => visitor.visit_mac(mac),
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ fn move_out_from_end() {
|
||||
|
||||
fn move_out_by_subslice() {
|
||||
let a = [box 1, box 2];
|
||||
let [_y..] = a;
|
||||
let [_y @ ..] = a;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -11,7 +11,7 @@ fn foldl<T, U, F>(values: &[T],
|
||||
U: Clone+Debug, T:Debug,
|
||||
F: FnMut(U, &T) -> U,
|
||||
{ match values {
|
||||
&[ref head, ref tail..] =>
|
||||
&[ref head, ref tail @ ..] =>
|
||||
foldl(tail, function(initial, head), function),
|
||||
&[] => {
|
||||
// FIXME: call guards
|
||||
@ -28,7 +28,7 @@ fn foldr<T, U, F>(values: &[T],
|
||||
F: FnMut(&T, U) -> U,
|
||||
{
|
||||
match values {
|
||||
&[ref head.., ref tail] =>
|
||||
&[ref head @ .., ref tail] =>
|
||||
foldr(head, function(tail, initial), function),
|
||||
&[] => {
|
||||
// FIXME: call guards
|
||||
|
@ -8,7 +8,7 @@ pub fn main() {
|
||||
let x: &[isize] = &[1, 2, 3, 4, 5];
|
||||
if !x.is_empty() {
|
||||
let el = match x {
|
||||
&[1, ref tail..] => &tail[0],
|
||||
&[1, ref tail @ ..] => &tail[0],
|
||||
_ => unreachable!()
|
||||
};
|
||||
println!("{}", *el);
|
||||
|
@ -14,7 +14,7 @@ fn a() {
|
||||
fn b() {
|
||||
let x = [1, 2, 3];
|
||||
match x {
|
||||
[a, b, c..] => {
|
||||
[a, b, c @ ..] => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
let expected: &[_] = &[3];
|
||||
@ -22,7 +22,7 @@ fn b() {
|
||||
}
|
||||
}
|
||||
match x {
|
||||
[a.., b, c] => {
|
||||
[a @ .., b, c] => {
|
||||
let expected: &[_] = &[1];
|
||||
assert_eq!(a, expected);
|
||||
assert_eq!(b, 2);
|
||||
@ -30,7 +30,7 @@ fn b() {
|
||||
}
|
||||
}
|
||||
match x {
|
||||
[a, b.., c] => {
|
||||
[a, b @ .., c] => {
|
||||
assert_eq!(a, 1);
|
||||
let expected: &[_] = &[2];
|
||||
assert_eq!(b, expected);
|
||||
@ -50,7 +50,7 @@ fn b() {
|
||||
fn b_slice() {
|
||||
let x : &[_] = &[1, 2, 3];
|
||||
match x {
|
||||
&[a, b, ref c..] => {
|
||||
&[a, b, ref c @ ..] => {
|
||||
assert_eq!(a, 1);
|
||||
assert_eq!(b, 2);
|
||||
let expected: &[_] = &[3];
|
||||
@ -59,7 +59,7 @@ fn b_slice() {
|
||||
_ => unreachable!()
|
||||
}
|
||||
match x {
|
||||
&[ref a.., b, c] => {
|
||||
&[ref a @ .., b, c] => {
|
||||
let expected: &[_] = &[1];
|
||||
assert_eq!(a, expected);
|
||||
assert_eq!(b, 2);
|
||||
@ -68,7 +68,7 @@ fn b_slice() {
|
||||
_ => unreachable!()
|
||||
}
|
||||
match x {
|
||||
&[a, ref b.., c] => {
|
||||
&[a, ref b @ .., c] => {
|
||||
assert_eq!(a, 1);
|
||||
let expected: &[_] = &[2];
|
||||
assert_eq!(b, expected);
|
||||
@ -134,20 +134,6 @@ fn e() {
|
||||
assert_eq!(c, 1);
|
||||
}
|
||||
|
||||
fn f() {
|
||||
let x = &[1, 2, 3, 4, 5];
|
||||
let [a, [b, [c, ..].., d].., e] = *x;
|
||||
assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
|
||||
|
||||
let x: &[isize] = x;
|
||||
let (a, b, c, d, e) = match *x {
|
||||
[a, [b, [c, ..].., d].., e] => (a, b, c, d, e),
|
||||
_ => unimplemented!()
|
||||
};
|
||||
|
||||
assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
a();
|
||||
b();
|
||||
@ -155,5 +141,4 @@ pub fn main() {
|
||||
c();
|
||||
d();
|
||||
e();
|
||||
f();
|
||||
}
|
||||
|
@ -13,14 +13,14 @@ pub fn main() {
|
||||
Foo { string: "baz" }
|
||||
];
|
||||
match x {
|
||||
[ref first, ref tail..] => {
|
||||
[ref first, ref tail @ ..] => {
|
||||
assert_eq!(first.string, "foo");
|
||||
assert_eq!(tail.len(), 2);
|
||||
assert_eq!(tail[0].string, "bar");
|
||||
assert_eq!(tail[1].string, "baz");
|
||||
|
||||
match *(tail as &[_]) {
|
||||
[Foo { .. }, _, Foo { .. }, ref _tail..] => {
|
||||
[Foo { .. }, _, Foo { .. }, ref _tail @ ..] => {
|
||||
unreachable!();
|
||||
}
|
||||
[Foo { string: ref a }, Foo { string: ref b }] => {
|
||||
|
@ -5,6 +5,5 @@ fn main() {
|
||||
let _ = <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
|
||||
let <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
|
||||
let 0 ..= <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
|
||||
//~^ ERROR only char and numeric types are allowed in range patterns
|
||||
<<A>::B>::C; //~ ERROR cannot find type `A` in this scope
|
||||
}
|
||||
|
@ -23,21 +23,11 @@ LL | let 0 ..= <<A>::B>::C;
|
||||
| ^ not found in this scope
|
||||
|
||||
error[E0412]: cannot find type `A` in this scope
|
||||
--> $DIR/associated-path-shl.rs:9:7
|
||||
--> $DIR/associated-path-shl.rs:8:7
|
||||
|
|
||||
LL | <<A>::B>::C;
|
||||
| ^ not found in this scope
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/associated-path-shl.rs:7:15
|
||||
|
|
||||
LL | let 0 ..= <<A>::B>::C;
|
||||
| ^^^^^^^^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: {integer}
|
||||
= note: end type: [type error]
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0029, E0412.
|
||||
For more information about an error, try `rustc --explain E0029`.
|
||||
For more information about this error, try `rustc --explain E0412`.
|
||||
|
@ -4,7 +4,7 @@
|
||||
#![feature(slice_patterns)]
|
||||
|
||||
fn foo(s: &[i32]) -> &[i32] {
|
||||
let &[ref xs..] = s;
|
||||
let &[ref xs @ ..] = s;
|
||||
xs
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,6 @@ fn main() {
|
||||
// The subslice used to go out of bounds for zero-sized array items, check that this doesn't
|
||||
// happen anymore
|
||||
match x {
|
||||
[_, ref y..] => assert_eq!(&x[1] as *const (), &y[0] as *const ())
|
||||
[_, ref y @ ..] => assert_eq!(&x[1] as *const (), &y[0] as *const ())
|
||||
}
|
||||
}
|
||||
|
@ -192,8 +192,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
||||
LL | let x = &mut v;
|
||||
| ------ borrow of `v` occurs here
|
||||
LL | match v {
|
||||
LL | &[x..] => println!("{:?}", x),
|
||||
| ^ use of borrowed `v`
|
||||
LL | &[x @ ..] => println!("{:?}", x),
|
||||
| ^^^^^^ use of borrowed `v`
|
||||
...
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
@ -204,8 +204,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
||||
LL | let x = &mut v;
|
||||
| ------ borrow of `v` occurs here
|
||||
...
|
||||
LL | &[_, x..] => println!("{:?}", x),
|
||||
| ^ use of borrowed `v`
|
||||
LL | &[_, x @ ..] => println!("{:?}", x),
|
||||
| ^^^^^^ use of borrowed `v`
|
||||
...
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
@ -216,8 +216,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
||||
LL | let x = &mut v;
|
||||
| ------ borrow of `v` occurs here
|
||||
...
|
||||
LL | &[x.., _] => println!("{:?}", x),
|
||||
| ^ use of borrowed `v`
|
||||
LL | &[x @ .., _] => println!("{:?}", x),
|
||||
| ^^^^^^ use of borrowed `v`
|
||||
...
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
@ -228,8 +228,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
||||
LL | let x = &mut v;
|
||||
| ------ borrow of `v` occurs here
|
||||
...
|
||||
LL | &[_, x.., _] => println!("{:?}", x),
|
||||
| ^ use of borrowed `v`
|
||||
LL | &[_, x @ .., _] => println!("{:?}", x),
|
||||
| ^^^^^^ use of borrowed `v`
|
||||
...
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
|
@ -140,22 +140,22 @@ fn main() {
|
||||
let mut v = &[1, 2, 3, 4, 5];
|
||||
let x = &mut v;
|
||||
match v {
|
||||
&[x..] => println!("{:?}", x),
|
||||
&[x @ ..] => println!("{:?}", x),
|
||||
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
||||
_ => panic!("other case"),
|
||||
}
|
||||
match v {
|
||||
&[_, x..] => println!("{:?}", x),
|
||||
&[_, x @ ..] => println!("{:?}", x),
|
||||
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
||||
_ => panic!("other case"),
|
||||
}
|
||||
match v {
|
||||
&[x.., _] => println!("{:?}", x),
|
||||
&[x @ .., _] => println!("{:?}", x),
|
||||
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
||||
_ => panic!("other case"),
|
||||
}
|
||||
match v {
|
||||
&[_, x.., _] => println!("{:?}", x),
|
||||
&[_, x @ .., _] => println!("{:?}", x),
|
||||
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
||||
_ => panic!("other case"),
|
||||
}
|
||||
|
@ -192,8 +192,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
||||
LL | let x = &mut v;
|
||||
| ------ borrow of `v` occurs here
|
||||
LL | match v {
|
||||
LL | &[x..] => println!("{:?}", x),
|
||||
| ^ use of borrowed `v`
|
||||
LL | &[x @ ..] => println!("{:?}", x),
|
||||
| ^^^^^^ use of borrowed `v`
|
||||
...
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
@ -204,8 +204,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
||||
LL | let x = &mut v;
|
||||
| ------ borrow of `v` occurs here
|
||||
...
|
||||
LL | &[_, x..] => println!("{:?}", x),
|
||||
| ^ use of borrowed `v`
|
||||
LL | &[_, x @ ..] => println!("{:?}", x),
|
||||
| ^^^^^^ use of borrowed `v`
|
||||
...
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
@ -216,8 +216,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
||||
LL | let x = &mut v;
|
||||
| ------ borrow of `v` occurs here
|
||||
...
|
||||
LL | &[x.., _] => println!("{:?}", x),
|
||||
| ^ use of borrowed `v`
|
||||
LL | &[x @ .., _] => println!("{:?}", x),
|
||||
| ^^^^^^ use of borrowed `v`
|
||||
...
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
@ -228,8 +228,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
||||
LL | let x = &mut v;
|
||||
| ------ borrow of `v` occurs here
|
||||
...
|
||||
LL | &[_, x.., _] => println!("{:?}", x),
|
||||
| ^ use of borrowed `v`
|
||||
LL | &[_, x @ .., _] => println!("{:?}", x),
|
||||
| ^^^^^^ use of borrowed `v`
|
||||
...
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
|
@ -10,7 +10,7 @@ fn move_out_from_begin_and_end() {
|
||||
fn move_out_by_const_index_and_subslice() {
|
||||
let a = [box 1, box 2];
|
||||
let [_x, _] = a;
|
||||
let [_y..] = a; //~ ERROR [E0382]
|
||||
let [_y @ ..] = a; //~ ERROR [E0382]
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -13,8 +13,8 @@ error[E0382]: use of moved value: `a[..]`
|
||||
|
|
||||
LL | let [_x, _] = a;
|
||||
| -- value moved here
|
||||
LL | let [_y..] = a;
|
||||
| ^^ value used here after move
|
||||
LL | let [_y @ ..] = a;
|
||||
| ^^^^^^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
|
||||
|
||||
|
@ -15,7 +15,7 @@ pub fn main() {
|
||||
];
|
||||
let x: &[Foo] = &x;
|
||||
match *x {
|
||||
[_, ref tail..] => {
|
||||
[_, ref tail @ ..] => {
|
||||
match tail {
|
||||
//~^ ERROR cannot move out of type `[Foo]`
|
||||
&[Foo { string: a },
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
fn mut_head_tail<'a, A>(v: &'a mut [A]) -> Option<(&'a mut A, &'a mut [A])> {
|
||||
match *v {
|
||||
[ref mut head, ref mut tail..] => {
|
||||
[ref mut head, ref mut tail @ ..] => {
|
||||
Some((head, tail))
|
||||
}
|
||||
[] => None
|
||||
|
@ -70,7 +70,7 @@ fn const_index_mixed(s: &mut [i32]) {
|
||||
|
||||
fn const_index_and_subslice_ok(s: &mut [i32]) {
|
||||
if let [ref first, ref second, ..] = *s {
|
||||
if let [_, _, ref mut tail..] = *s {
|
||||
if let [_, _, ref mut tail @ ..] = *s {
|
||||
nop(&[first, second]);
|
||||
nop_subslice(tail);
|
||||
}
|
||||
@ -79,7 +79,7 @@ fn const_index_and_subslice_ok(s: &mut [i32]) {
|
||||
|
||||
fn const_index_and_subslice_err(s: &mut [i32]) {
|
||||
if let [ref first, ref second, ..] = *s {
|
||||
if let [_, ref mut tail..] = *s { //~ERROR
|
||||
if let [_, ref mut tail @ ..] = *s { //~ERROR
|
||||
nop(&[first, second]);
|
||||
nop_subslice(tail);
|
||||
}
|
||||
@ -88,7 +88,7 @@ fn const_index_and_subslice_err(s: &mut [i32]) {
|
||||
|
||||
fn const_index_and_subslice_from_end_ok(s: &mut [i32]) {
|
||||
if let [.., ref second, ref first] = *s {
|
||||
if let [ref mut tail.., _, _] = *s {
|
||||
if let [ref mut tail @ .., _, _] = *s {
|
||||
nop(&[first, second]);
|
||||
nop_subslice(tail);
|
||||
}
|
||||
@ -97,7 +97,7 @@ fn const_index_and_subslice_from_end_ok(s: &mut [i32]) {
|
||||
|
||||
fn const_index_and_subslice_from_end_err(s: &mut [i32]) {
|
||||
if let [.., ref second, ref first] = *s {
|
||||
if let [ref mut tail.., _] = *s { //~ERROR
|
||||
if let [ref mut tail @ .., _] = *s { //~ERROR
|
||||
nop(&[first, second]);
|
||||
nop_subslice(tail);
|
||||
}
|
||||
@ -105,8 +105,8 @@ fn const_index_and_subslice_from_end_err(s: &mut [i32]) {
|
||||
}
|
||||
|
||||
fn subslices(s: &mut [i32]) {
|
||||
if let [_, _, _, ref s1..] = *s {
|
||||
if let [ref mut s2.., _, _, _] = *s { //~ERROR
|
||||
if let [_, _, _, ref s1 @ ..] = *s {
|
||||
if let [ref mut s2 @ .., _, _, _] = *s { //~ERROR
|
||||
nop_subslice(s1);
|
||||
nop_subslice(s2);
|
||||
}
|
||||
|
@ -89,8 +89,8 @@ error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as im
|
||||
|
|
||||
LL | if let [ref first, ref second, ..] = *s {
|
||||
| ---------- immutable borrow occurs here
|
||||
LL | if let [_, ref mut tail..] = *s {
|
||||
| ^^^^^^^^^^^^ mutable borrow occurs here
|
||||
LL | if let [_, ref mut tail @ ..] = *s {
|
||||
| ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||
LL | nop(&[first, second]);
|
||||
| ------ immutable borrow later used here
|
||||
|
||||
@ -99,18 +99,18 @@ error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as im
|
||||
|
|
||||
LL | if let [.., ref second, ref first] = *s {
|
||||
| ---------- immutable borrow occurs here
|
||||
LL | if let [ref mut tail.., _] = *s {
|
||||
| ^^^^^^^^^^^^ mutable borrow occurs here
|
||||
LL | if let [ref mut tail @ .., _] = *s {
|
||||
| ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||
LL | nop(&[first, second]);
|
||||
| ------ immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-slice-pattern-element-loan.rs:109:17
|
||||
|
|
||||
LL | if let [_, _, _, ref s1..] = *s {
|
||||
| ------ immutable borrow occurs here
|
||||
LL | if let [ref mut s2.., _, _, _] = *s {
|
||||
| ^^^^^^^^^^ mutable borrow occurs here
|
||||
LL | if let [_, _, _, ref s1 @ ..] = *s {
|
||||
| ----------- immutable borrow occurs here
|
||||
LL | if let [ref mut s2 @ .., _, _, _] = *s {
|
||||
| ^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||
LL | nop_subslice(s1);
|
||||
| -- immutable borrow later used here
|
||||
|
||||
|
@ -4,7 +4,7 @@ fn a<'a>() -> &'a [isize] {
|
||||
let vec = vec![1, 2, 3, 4];
|
||||
let vec: &[isize] = &vec;
|
||||
let tail = match vec {
|
||||
&[_, ref tail..] => tail,
|
||||
&[_, ref tail @ ..] => tail,
|
||||
_ => panic!("a")
|
||||
};
|
||||
tail //~ ERROR cannot return value referencing local variable `vec`
|
||||
@ -14,7 +14,7 @@ fn b<'a>() -> &'a [isize] {
|
||||
let vec = vec![1, 2, 3, 4];
|
||||
let vec: &[isize] = &vec;
|
||||
let init = match vec {
|
||||
&[ref init.., _] => init,
|
||||
&[ref init @ .., _] => init,
|
||||
_ => panic!("b")
|
||||
};
|
||||
init //~ ERROR cannot return value referencing local variable `vec`
|
||||
@ -24,7 +24,7 @@ fn c<'a>() -> &'a [isize] {
|
||||
let vec = vec![1, 2, 3, 4];
|
||||
let vec: &[isize] = &vec;
|
||||
let slice = match vec {
|
||||
&[_, ref slice.., _] => slice,
|
||||
&[_, ref slice @ .., _] => slice,
|
||||
_ => panic!("c")
|
||||
};
|
||||
slice //~ ERROR cannot return value referencing local variable `vec`
|
||||
|
@ -4,7 +4,7 @@ fn a() {
|
||||
let mut v = vec![1, 2, 3];
|
||||
let vb: &mut [isize] = &mut v;
|
||||
match vb {
|
||||
&mut [_a, ref tail..] => {
|
||||
&mut [_a, ref tail @ ..] => {
|
||||
v.push(tail[0] + tail[1]); //~ ERROR cannot borrow
|
||||
}
|
||||
_ => {}
|
||||
|
@ -5,7 +5,7 @@
|
||||
fn main() {
|
||||
let mut a = [1, 2, 3, 4];
|
||||
let t = match a {
|
||||
[1, 2, ref tail..] => tail,
|
||||
[1, 2, ref tail @ ..] => tail,
|
||||
_ => unreachable!()
|
||||
};
|
||||
println!("t[0]: {}", t[0]);
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0506]: cannot assign to `a[_]` because it is borrowed
|
||||
--> $DIR/borrowck-vec-pattern-move-tail.rs:12:5
|
||||
|
|
||||
LL | [1, 2, ref tail..] => tail,
|
||||
| -------- borrow of `a[_]` occurs here
|
||||
LL | [1, 2, ref tail @ ..] => tail,
|
||||
| ------------- borrow of `a[_]` occurs here
|
||||
...
|
||||
LL | a[2] = 0;
|
||||
| ^^^^^^^^ assignment to borrowed `a[_]` occurs here
|
||||
|
@ -19,7 +19,7 @@ fn b() {
|
||||
let mut vec = vec![box 1, box 2, box 3];
|
||||
let vec: &mut [Box<isize>] = &mut vec;
|
||||
match vec {
|
||||
&mut [ref _b..] => {
|
||||
&mut [ref _b @ ..] => {
|
||||
//~^ borrow of `vec[_]` occurs here
|
||||
vec[0] = box 4; //~ ERROR cannot assign
|
||||
//~^ NOTE assignment to borrowed `vec[_]` occurs here
|
||||
|
@ -13,8 +13,8 @@ LL | _a.use_ref();
|
||||
error[E0506]: cannot assign to `vec[_]` because it is borrowed
|
||||
--> $DIR/borrowck-vec-pattern-nesting.rs:24:13
|
||||
|
|
||||
LL | &mut [ref _b..] => {
|
||||
| ------ borrow of `vec[_]` occurs here
|
||||
LL | &mut [ref _b @ ..] => {
|
||||
| ----------- borrow of `vec[_]` occurs here
|
||||
LL |
|
||||
LL | vec[0] = box 4;
|
||||
| ^^^^^^ assignment to borrowed `vec[_]` occurs here
|
||||
|
@ -4,7 +4,7 @@ fn a<'a>() -> &'a isize {
|
||||
let vec = vec![1, 2, 3, 4];
|
||||
let vec: &[isize] = &vec;
|
||||
let tail = match vec {
|
||||
&[_a, ref tail..] => &tail[0],
|
||||
&[_a, ref tail @ ..] => &tail[0],
|
||||
_ => panic!("foo")
|
||||
};
|
||||
tail //~ ERROR cannot return value referencing local variable `vec`
|
||||
|
@ -217,7 +217,7 @@ async fn subslice_pattern_from_end_with_drop(a: Rc<Allocator>, arg: bool, arg2:
|
||||
if arg {
|
||||
let [.., _x, _] = arr;
|
||||
} else {
|
||||
let [_, _y..] = arr;
|
||||
let [_, _y @ ..] = arr;
|
||||
}
|
||||
a.alloc().await;
|
||||
}
|
||||
@ -226,7 +226,7 @@ async fn subslice_pattern_reassign(a: Rc<Allocator>) {
|
||||
let mut ar = [a.alloc().await, a.alloc().await, a.alloc().await];
|
||||
let [_, _, _x] = ar;
|
||||
ar = [a.alloc().await, a.alloc().await, a.alloc().await];
|
||||
let [_, _y..] = ar;
|
||||
let [_, _y @ ..] = ar;
|
||||
a.alloc().await;
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ fn subslice_pattern_from_end(a: &Allocator, arg: bool) {
|
||||
if arg {
|
||||
let[.., _x, _] = a;
|
||||
} else {
|
||||
let[_, _y..] = a;
|
||||
let[_, _y @ ..] = a;
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,7 +251,7 @@ fn subslice_pattern_from_end_with_drop(a: &Allocator, arg: bool, arg2: bool) {
|
||||
if arg {
|
||||
let[.., _x, _] = a;
|
||||
} else {
|
||||
let[_, _y..] = a;
|
||||
let[_, _y @ ..] = a;
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,7 +266,7 @@ fn subslice_pattern_reassign(a: &Allocator) {
|
||||
let mut ar = [a.alloc(), a.alloc(), a.alloc()];
|
||||
let[_, _, _x] = ar;
|
||||
ar = [a.alloc(), a.alloc(), a.alloc()];
|
||||
let[_, _y..] = ar;
|
||||
let[_, _y @ ..] = ar;
|
||||
}
|
||||
|
||||
fn panic_after_return(a: &Allocator) -> Ptr<'_> {
|
||||
|
@ -3,7 +3,7 @@
|
||||
fn main() {
|
||||
let r = &[1, 2];
|
||||
match r {
|
||||
&[a, b, c, rest..] => {
|
||||
&[a, b, c, rest @ ..] => {
|
||||
//~^ ERROR E0528
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0528]: pattern requires at least 3 elements but array has 2
|
||||
--> $DIR/E0528.rs:6:10
|
||||
|
|
||||
LL | &[a, b, c, rest..] => {
|
||||
| ^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements
|
||||
LL | &[a, b, c, rest @ ..] => {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
fn main() {
|
||||
match [5..4, 99..105, 43..44] {
|
||||
[_, 99.., _] => {}, //~ ERROR unexpected token: `,`
|
||||
[_, 99.., _] => {},
|
||||
//~^ ERROR `X..` range patterns are not supported
|
||||
//~| ERROR mismatched types
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,20 @@
|
||||
error: unexpected token: `,`
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision.rs:5:17
|
||||
error: `X..` range patterns are not supported
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
|
||||
|
|
||||
LL | [_, 99.., _] => {},
|
||||
| ^
|
||||
| ^^^^ help: try using the maximum value for the type: `99..MAX`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
|
||||
|
|
||||
LL | match [5..4, 99..105, 43..44] {
|
||||
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
|
||||
LL | [_, 99.., _] => {},
|
||||
| ^^^^ expected struct `std::ops::Range`, found integer
|
||||
|
|
||||
= note: expected type `std::ops::Range<{integer}>`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -2,7 +2,10 @@
|
||||
|
||||
fn main() {
|
||||
match [5..4, 99..105, 43..44] {
|
||||
[_, 99..] => {}, //~ ERROR unexpected token: `]`
|
||||
[_, 99..] => {},
|
||||
//~^ ERROR `X..` range patterns are not supported
|
||||
//~| ERROR pattern requires 2 elements but array has 3
|
||||
//~| ERROR mismatched types
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,27 @@
|
||||
error: unexpected token: `]`
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:17
|
||||
error: `X..` range patterns are not supported
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
|
||||
|
|
||||
LL | [_, 99..] => {},
|
||||
| ^
|
||||
| ^^^^ help: try using the maximum value for the type: `99..MAX`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0527]: pattern requires 2 elements but array has 3
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:9
|
||||
|
|
||||
LL | [_, 99..] => {},
|
||||
| ^^^^^^^^^ expected 3 elements
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
|
||||
|
|
||||
LL | match [5..4, 99..105, 43..44] {
|
||||
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
|
||||
LL | [_, 99..] => {},
|
||||
| ^^^^ expected struct `std::ops::Range`, found integer
|
||||
|
|
||||
= note: expected type `std::ops::Range<{integer}>`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0527.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -2,7 +2,10 @@
|
||||
|
||||
fn main() {
|
||||
match [5..4, 99..105, 43..44] {
|
||||
[..9, 99..100, _] => {}, //~ ERROR expected one of `,` or `]`, found `9`
|
||||
[..9, 99..100, _] => {},
|
||||
//~^ ERROR `..X` range patterns are not supported
|
||||
//~| ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,31 @@
|
||||
error: expected one of `,` or `]`, found `9`
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
|
||||
error: `..X` range patterns are not supported
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
|
||||
|
|
||||
LL | [..9, 99..100, _] => {},
|
||||
| ^ expected one of `,` or `]` here
|
||||
| ^^^ help: try using the minimum value for the type: `MIN..9`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
|
||||
|
|
||||
LL | match [5..4, 99..105, 43..44] {
|
||||
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
|
||||
LL | [..9, 99..100, _] => {},
|
||||
| ^^^ expected struct `std::ops::Range`, found integer
|
||||
|
|
||||
= note: expected type `std::ops::Range<{integer}>`
|
||||
found type `{integer}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15
|
||||
|
|
||||
LL | match [5..4, 99..105, 43..44] {
|
||||
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
|
||||
LL | [..9, 99..100, _] => {},
|
||||
| ^^^^^^^ expected struct `std::ops::Range`, found integer
|
||||
|
|
||||
= note: expected type `std::ops::Range<{integer}>`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -3,15 +3,15 @@
|
||||
fn main() {
|
||||
let x = [1, 2, 3, 4, 5];
|
||||
match x {
|
||||
[1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
||||
[1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
||||
[.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
||||
[1, 2, ..] => {} //~ ERROR subslice patterns are unstable
|
||||
[1, .., 5] => {} //~ ERROR subslice patterns are unstable
|
||||
[.., 4, 5] => {} //~ ERROR subslice patterns are unstable
|
||||
}
|
||||
|
||||
let x = [ 1, 2, 3, 4, 5 ];
|
||||
match x {
|
||||
[ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
||||
[ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
||||
[ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
||||
[ xs @ .., 4, 5 ] => {} //~ ERROR subslice patterns are unstable
|
||||
[ 1, xs @ .., 5 ] => {} //~ ERROR subslice patterns are unstable
|
||||
[ 1, 2, xs @ .. ] => {} //~ ERROR subslice patterns are unstable
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
|
||||
error[E0658]: subslice patterns are unstable
|
||||
--> $DIR/feature-gate-slice-patterns.rs:6:16
|
||||
|
|
||||
LL | [1, 2, ..] => {}
|
||||
@ -7,7 +7,7 @@ LL | [1, 2, ..] => {}
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
|
||||
error[E0658]: subslice patterns are unstable
|
||||
--> $DIR/feature-gate-slice-patterns.rs:7:13
|
||||
|
|
||||
LL | [1, .., 5] => {}
|
||||
@ -16,7 +16,7 @@ LL | [1, .., 5] => {}
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
|
||||
error[E0658]: subslice patterns are unstable
|
||||
--> $DIR/feature-gate-slice-patterns.rs:8:10
|
||||
|
|
||||
LL | [.., 4, 5] => {}
|
||||
@ -25,29 +25,29 @@ LL | [.., 4, 5] => {}
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
|
||||
error[E0658]: subslice patterns are unstable
|
||||
--> $DIR/feature-gate-slice-patterns.rs:13:11
|
||||
|
|
||||
LL | [ xs.., 4, 5 ] => {}
|
||||
| ^^
|
||||
LL | [ xs @ .., 4, 5 ] => {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
|
||||
error[E0658]: subslice patterns are unstable
|
||||
--> $DIR/feature-gate-slice-patterns.rs:14:14
|
||||
|
|
||||
LL | [ 1, xs.., 5 ] => {}
|
||||
| ^^
|
||||
LL | [ 1, xs @ .., 5 ] => {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
|
||||
error[E0658]: subslice patterns are unstable
|
||||
--> $DIR/feature-gate-slice-patterns.rs:15:17
|
||||
|
|
||||
LL | [ 1, 2, xs.. ] => {}
|
||||
| ^^
|
||||
LL | [ 1, 2, xs @ .. ] => {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
||||
|
@ -6,7 +6,7 @@ fn main() {
|
||||
let v: isize = match &*sl {
|
||||
&[] => 0,
|
||||
&[a,b,c] => 3,
|
||||
&[a, ref rest..] => a,
|
||||
&[10,a, ref rest..] => 10 //~ ERROR: unreachable pattern
|
||||
&[a, ref rest @ ..] => a,
|
||||
&[10,a, ref rest @ ..] => 10 //~ ERROR: unreachable pattern
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: unreachable pattern
|
||||
--> $DIR/issue-12369.rs:10:9
|
||||
|
|
||||
LL | &[10,a, ref rest..] => 10
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
LL | &[10,a, ref rest @ ..] => 10
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/issue-12369.rs:2:9
|
||||
|
@ -7,11 +7,11 @@ fn main() {
|
||||
let mut result = vec![];
|
||||
loop {
|
||||
x = match *x {
|
||||
[1, n, 3, ref rest..] => {
|
||||
[1, n, 3, ref rest @ ..] => {
|
||||
result.push(n);
|
||||
rest
|
||||
}
|
||||
[n, ref rest..] => {
|
||||
[n, ref rest @ ..] => {
|
||||
result.push(n);
|
||||
rest
|
||||
}
|
||||
|
@ -9,6 +9,6 @@ fn count_members(v: &[usize]) -> usize {
|
||||
match *v {
|
||||
[] => 0,
|
||||
[_] => 1,
|
||||
[_, ref xs..] => 1 + count_members(xs)
|
||||
[_, ref xs @ ..] => 1 + count_members(xs)
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ fn main() {
|
||||
}, 42_usize);
|
||||
|
||||
assert_eq!(match [0u8; 1024] {
|
||||
[1, _..] => 0_usize,
|
||||
[0, _..] => 1_usize,
|
||||
[1, ..] => 0_usize,
|
||||
[0, ..] => 1_usize,
|
||||
_ => 2_usize
|
||||
}, 1_usize);
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
#![feature(slice_patterns)]
|
||||
|
||||
fn main() {
|
||||
let x: &[u32] = &[];
|
||||
let &[[ref _a, ref _b..]..] = x; //~ ERROR refutable pattern
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
error[E0005]: refutable pattern in local binding: `&[]` not covered
|
||||
--> $DIR/issue-26158.rs:5:9
|
||||
|
|
||||
LL | let &[[ref _a, ref _b..]..] = x;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ pattern `&[]` not covered
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0005`.
|
@ -1,11 +1,10 @@
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
#![allow(dead_code)]
|
||||
// check-pass
|
||||
#![feature(slice_patterns)]
|
||||
|
||||
fn check(list: &[u8]) {
|
||||
match list {
|
||||
&[] => {},
|
||||
&[_u1, _u2, ref _next..] => {},
|
||||
&[_u1, _u2, ref _next @ ..] => {},
|
||||
&[_u1] => {},
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ fn main() {
|
||||
assert_eq!(d, "baz");
|
||||
|
||||
let out = bar("baz", "foo");
|
||||
let [a, xs.., d] = out;
|
||||
let [a, xs @ .., d] = out;
|
||||
assert_eq!(a, "baz");
|
||||
assert_eq!(xs, ["foo", "foo"]);
|
||||
assert_eq!(d, "baz");
|
||||
|
@ -19,10 +19,10 @@ fn main() {
|
||||
match [0, 1, 2] {
|
||||
[0] => {}, //~ ERROR pattern requires
|
||||
|
||||
[0, 1, x..] => {
|
||||
[0, 1, x @ ..] => {
|
||||
let a: [_; 1] = x;
|
||||
}
|
||||
[0, 1, 2, 3, x..] => {} //~ ERROR pattern requires
|
||||
[0, 1, 2, 3, x @ ..] => {} //~ ERROR pattern requires
|
||||
};
|
||||
|
||||
match does_not_exist { //~ ERROR cannot find value `does_not_exist` in this scope
|
||||
|
@ -19,8 +19,8 @@ LL | [0] => {},
|
||||
error[E0528]: pattern requires at least 4 elements but array has 3
|
||||
--> $DIR/match-vec-mismatch.rs:25:9
|
||||
|
|
||||
LL | [0, 1, 2, 3, x..] => {}
|
||||
| ^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
|
||||
LL | [0, 1, 2, 3, x @ ..] => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/match-vec-mismatch.rs:36:9
|
||||
|
@ -23,7 +23,7 @@ fn main() {
|
||||
let x: Vec<char> = vec!['a', 'b', 'c'];
|
||||
let x: &[char] = &x;
|
||||
match *x {
|
||||
['a', 'b', 'c', ref _tail..] => {}
|
||||
['a', 'b', 'c', ref _tail @ ..] => {}
|
||||
['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
|
||||
_ => {}
|
||||
}
|
||||
|
@ -32,14 +32,14 @@ fn main() {
|
||||
let vec = vec![Some(42), None, Some(21)];
|
||||
let vec: &[Option<isize>] = &vec;
|
||||
match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered
|
||||
[Some(..), None, ref tail..] => {}
|
||||
[Some(..), Some(..), ref tail..] => {}
|
||||
[Some(..), None, ref tail @ ..] => {}
|
||||
[Some(..), Some(..), ref tail @ ..] => {}
|
||||
[None] => {}
|
||||
}
|
||||
let vec = vec![1];
|
||||
let vec: &[isize] = &vec;
|
||||
match *vec {
|
||||
[_, ref tail..] => (),
|
||||
[_, ref tail @ ..] => (),
|
||||
[] => ()
|
||||
}
|
||||
let vec = vec![0.5f32];
|
||||
@ -53,10 +53,10 @@ fn main() {
|
||||
let vec = vec![Some(42), None, Some(21)];
|
||||
let vec: &[Option<isize>] = &vec;
|
||||
match *vec {
|
||||
[Some(..), None, ref tail..] => {}
|
||||
[Some(..), Some(..), ref tail..] => {}
|
||||
[None, None, ref tail..] => {}
|
||||
[None, Some(..), ref tail..] => {}
|
||||
[Some(..), None, ref tail @ ..] => {}
|
||||
[Some(..), Some(..), ref tail @ ..] => {}
|
||||
[None, None, ref tail @ ..] => {}
|
||||
[None, Some(..), ref tail @ ..] => {}
|
||||
[Some(_)] => {}
|
||||
[None] => {}
|
||||
[] => {}
|
||||
|
@ -77,7 +77,7 @@ fn vectors_with_nested_enums() {
|
||||
[Enum::Second(true), Enum::First] => (),
|
||||
[Enum::Second(true), Enum::Second(true)] => (),
|
||||
[Enum::Second(false), _] => (),
|
||||
[_, _, ref tail.., _] => ()
|
||||
[_, _, ref tail @ .., _] => ()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,13 @@
|
||||
fn main() {
|
||||
let a = Vec::new();
|
||||
let a: &[u8] = &[];
|
||||
match a {
|
||||
[1, tail.., tail..] => {}, //~ ERROR: expected one of `,` or `@`, found `..`
|
||||
[1, tail @ .., tail @ ..] => {},
|
||||
//~^ ERROR identifier `tail` is bound more than once in the same pattern
|
||||
//~| ERROR subslice patterns are unstable
|
||||
//~| ERROR subslice patterns are unstable
|
||||
//~| ERROR `..` can only be used once per slice pattern
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
|
||||
|
@ -1,8 +1,45 @@
|
||||
error: expected one of `,` or `@`, found `..`
|
||||
--> $DIR/match-vec-invalid.rs:4:25
|
||||
error[E0416]: identifier `tail` is bound more than once in the same pattern
|
||||
--> $DIR/match-vec-invalid.rs:4:24
|
||||
|
|
||||
LL | [1, tail.., tail..] => {},
|
||||
| ^^ expected one of `,` or `@` here
|
||||
LL | [1, tail @ .., tail @ ..] => {},
|
||||
| ^^^^ used in a pattern more than once
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0658]: subslice patterns are unstable
|
||||
--> $DIR/match-vec-invalid.rs:4:13
|
||||
|
|
||||
LL | [1, tail @ .., tail @ ..] => {},
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: subslice patterns are unstable
|
||||
--> $DIR/match-vec-invalid.rs:4:24
|
||||
|
|
||||
LL | [1, tail @ .., tail @ ..] => {},
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
||||
|
||||
error: `..` can only be used once per slice pattern
|
||||
--> $DIR/match-vec-invalid.rs:4:31
|
||||
|
|
||||
LL | [1, tail @ .., tail @ ..] => {},
|
||||
| -- ^^ can only be used once per slice pattern
|
||||
| |
|
||||
| previously used here
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/match-vec-invalid.rs:13:30
|
||||
|
|
||||
LL | const RECOVERY_WITNESS: () = 0;
|
||||
| ^ expected (), found integer
|
||||
|
|
||||
= note: expected type `()`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0416, E0658.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -1,3 +1,9 @@
|
||||
fn main() {
|
||||
struct Test(&'static u8, [u8; 0]);
|
||||
let x = Test(&0, []);
|
||||
|
||||
let Test(&desc[..]) = x; //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
|
||||
//~^ ERROR subslice patterns are unstable
|
||||
}
|
||||
|
||||
const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
|
||||
|
@ -1,8 +1,28 @@
|
||||
error: expected one of `)`, `,`, or `@`, found `[`
|
||||
--> $DIR/pat-lt-bracket-6.rs:2:19
|
||||
--> $DIR/pat-lt-bracket-6.rs:5:19
|
||||
|
|
||||
LL | let Test(&desc[..]) = x;
|
||||
| ^ expected one of `)`, `,`, or `@` here
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0658]: subslice patterns are unstable
|
||||
--> $DIR/pat-lt-bracket-6.rs:5:20
|
||||
|
|
||||
LL | let Test(&desc[..]) = x;
|
||||
| ^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-lt-bracket-6.rs:9:30
|
||||
|
|
||||
LL | const RECOVERY_WITNESS: () = 0;
|
||||
| ^ expected (), found integer
|
||||
|
|
||||
= note: expected type `()`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0658.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -1,3 +1,8 @@
|
||||
fn main() {
|
||||
for thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
|
||||
struct Thing(u8, [u8; 0]);
|
||||
let foo = core::iter::empty();
|
||||
|
||||
for Thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
|
||||
}
|
||||
|
||||
const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
|
||||
|
@ -1,8 +1,18 @@
|
||||
error: expected one of `)`, `,`, or `@`, found `[`
|
||||
--> $DIR/pat-lt-bracket-7.rs:2:16
|
||||
--> $DIR/pat-lt-bracket-7.rs:5:16
|
||||
|
|
||||
LL | for thing(x[]) in foo {}
|
||||
LL | for Thing(x[]) in foo {}
|
||||
| ^ expected one of `)`, `,`, or `@` here
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-lt-bracket-7.rs:8:30
|
||||
|
|
||||
LL | const RECOVERY_WITNESS: () = 0;
|
||||
| ^ expected (), found integer
|
||||
|
|
||||
= note: expected type `()`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,6 +1,7 @@
|
||||
// check-pass
|
||||
|
||||
fn main() {
|
||||
match (0, 1, 2) {
|
||||
(pat, ..,) => {}
|
||||
//~^ ERROR trailing comma is not permitted after `..`
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
error: trailing comma is not permitted after `..`
|
||||
--> $DIR/pat-tuple-2.rs:3:17
|
||||
|
|
||||
LL | (pat, ..,) => {}
|
||||
| ^ trailing comma is not permitted after `..`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,6 +1,6 @@
|
||||
fn main() {
|
||||
match (0, 1, 2) {
|
||||
(.., pat, ..) => {}
|
||||
//~^ ERROR `..` can only be used once per tuple or tuple struct pattern
|
||||
//~^ ERROR `..` can only be used once per tuple pattern
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: `..` can only be used once per tuple or tuple struct pattern
|
||||
error: `..` can only be used once per tuple pattern
|
||||
--> $DIR/pat-tuple-3.rs:3:19
|
||||
|
|
||||
LL | (.., pat, ..) => {}
|
||||
| -- ^^ can only be used once per pattern
|
||||
| -- ^^ can only be used once per tuple pattern
|
||||
| |
|
||||
| previously present here
|
||||
| previously used here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,5 +1,11 @@
|
||||
fn main() {
|
||||
const PAT: u8 = 0;
|
||||
|
||||
match 0 {
|
||||
(.. pat) => {} //~ ERROR expected one of `)` or `,`, found `pat`
|
||||
(.. PAT) => {}
|
||||
//~^ ERROR `..X` range patterns are not supported
|
||||
//~| ERROR exclusive range pattern syntax is experimental
|
||||
}
|
||||
}
|
||||
|
||||
const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
|
||||
|
@ -1,8 +1,28 @@
|
||||
error: expected one of `)` or `,`, found `pat`
|
||||
--> $DIR/pat-tuple-4.rs:3:13
|
||||
error: `..X` range patterns are not supported
|
||||
--> $DIR/pat-tuple-4.rs:5:10
|
||||
|
|
||||
LL | (.. pat) => {}
|
||||
| ^^^ expected one of `)` or `,` here
|
||||
LL | (.. PAT) => {}
|
||||
| ^^^^^^ help: try using the minimum value for the type: `MIN..PAT`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0658]: exclusive range pattern syntax is experimental
|
||||
--> $DIR/pat-tuple-4.rs:5:10
|
||||
|
|
||||
LL | (.. PAT) => {}
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/37854
|
||||
= help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-tuple-4.rs:11:30
|
||||
|
|
||||
LL | const RECOVERY_WITNESS: () = 0;
|
||||
| ^ expected (), found integer
|
||||
|
|
||||
= note: expected type `()`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0658.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -1,5 +1,10 @@
|
||||
fn main() {
|
||||
const PAT: u8 = 0;
|
||||
|
||||
match (0, 1) {
|
||||
(pat ..) => {} //~ ERROR unexpected token: `)`
|
||||
(PAT ..) => {}
|
||||
//~^ ERROR `X..` range patterns are not supported
|
||||
//~| ERROR exclusive range pattern syntax is experimental
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,30 @@
|
||||
error: unexpected token: `)`
|
||||
--> $DIR/pat-tuple-5.rs:3:16
|
||||
error: `X..` range patterns are not supported
|
||||
--> $DIR/pat-tuple-5.rs:5:10
|
||||
|
|
||||
LL | (pat ..) => {}
|
||||
| ^
|
||||
LL | (PAT ..) => {}
|
||||
| ^^^^^^ help: try using the maximum value for the type: `PAT..MAX`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0658]: exclusive range pattern syntax is experimental
|
||||
--> $DIR/pat-tuple-5.rs:5:10
|
||||
|
|
||||
LL | (PAT ..) => {}
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/37854
|
||||
= help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-tuple-5.rs:5:10
|
||||
|
|
||||
LL | match (0, 1) {
|
||||
| ------ this match expression has type `({integer}, {integer})`
|
||||
LL | (PAT ..) => {}
|
||||
| ^^^^^^ expected tuple, found u8
|
||||
|
|
||||
= note: expected type `({integer}, {integer})`
|
||||
found type `u8`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0658.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
123
src/test/ui/parser/recover-range-pats.rs
Normal file
123
src/test/ui/parser/recover-range-pats.rs
Normal file
@ -0,0 +1,123 @@
|
||||
// Here we test all kinds of range patterns in terms of parsing / recovery.
|
||||
// We want to ensure that:
|
||||
// 1. Things parse as they should.
|
||||
// 2. Or at least we have parser recovery if they don't.
|
||||
|
||||
#![feature(exclusive_range_pattern)]
|
||||
#![deny(ellipsis_inclusive_range_patterns)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
const X: u8 = 0;
|
||||
const Y: u8 = 3;
|
||||
|
||||
fn exclusive_from_to() {
|
||||
if let 0..3 = 0 {} // OK.
|
||||
if let 0..Y = 0 {} // OK.
|
||||
if let X..3 = 0 {} // OK.
|
||||
if let X..Y = 0 {} // OK.
|
||||
if let true..Y = 0 {} //~ ERROR only char and numeric types
|
||||
if let X..true = 0 {} //~ ERROR only char and numeric types
|
||||
if let .0..Y = 0 {} //~ ERROR mismatched types
|
||||
//~^ ERROR float literals must have an integer part
|
||||
if let X.. .0 = 0 {} //~ ERROR mismatched types
|
||||
//~^ ERROR float literals must have an integer part
|
||||
}
|
||||
|
||||
fn inclusive_from_to() {
|
||||
if let 0..=3 = 0 {} // OK.
|
||||
if let 0..=Y = 0 {} // OK.
|
||||
if let X..=3 = 0 {} // OK.
|
||||
if let X..=Y = 0 {} // OK.
|
||||
if let true..=Y = 0 {} //~ ERROR only char and numeric types
|
||||
if let X..=true = 0 {} //~ ERROR only char and numeric types
|
||||
if let .0..=Y = 0 {} //~ ERROR mismatched types
|
||||
//~^ ERROR float literals must have an integer part
|
||||
if let X..=.0 = 0 {} //~ ERROR mismatched types
|
||||
//~^ ERROR float literals must have an integer part
|
||||
}
|
||||
|
||||
fn inclusive2_from_to() {
|
||||
if let 0...3 = 0 {} //~ ERROR `...` range patterns are deprecated
|
||||
if let 0...Y = 0 {} //~ ERROR `...` range patterns are deprecated
|
||||
if let X...3 = 0 {} //~ ERROR `...` range patterns are deprecated
|
||||
if let X...Y = 0 {} //~ ERROR `...` range patterns are deprecated
|
||||
if let true...Y = 0 {} //~ ERROR only char and numeric types
|
||||
//~^ ERROR `...` range patterns are deprecated
|
||||
if let X...true = 0 {} //~ ERROR only char and numeric types
|
||||
//~^ ERROR `...` range patterns are deprecated
|
||||
if let .0...Y = 0 {} //~ ERROR mismatched types
|
||||
//~^ ERROR float literals must have an integer part
|
||||
//~| ERROR `...` range patterns are deprecated
|
||||
if let X... .0 = 0 {} //~ ERROR mismatched types
|
||||
//~^ ERROR float literals must have an integer part
|
||||
//~| ERROR `...` range patterns are deprecated
|
||||
}
|
||||
|
||||
fn exclusive_from() {
|
||||
if let 0.. = 0 {} //~ ERROR `X..` range patterns are not supported
|
||||
if let X.. = 0 {} //~ ERROR `X..` range patterns are not supported
|
||||
if let true.. = 0 {} //~ ERROR `X..` range patterns are not supported
|
||||
//~^ ERROR only char and numeric types
|
||||
if let .0.. = 0 {} //~ ERROR `X..` range patterns are not supported
|
||||
//~^ ERROR float literals must have an integer part
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn inclusive_from() {
|
||||
if let 0..= = 0 {} //~ ERROR `X..=` range patterns are not supported
|
||||
if let X..= = 0 {} //~ ERROR `X..=` range patterns are not supported
|
||||
if let true..= = 0 {} //~ ERROR `X..=` range patterns are not supported
|
||||
//~| ERROR only char and numeric types
|
||||
if let .0..= = 0 {} //~ ERROR `X..=` range patterns are not supported
|
||||
//~^ ERROR float literals must have an integer part
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn inclusive2_from() {
|
||||
if let 0... = 0 {} //~ ERROR `X...` range patterns are not supported
|
||||
//~^ ERROR `...` range patterns are deprecated
|
||||
if let X... = 0 {} //~ ERROR `X...` range patterns are not supported
|
||||
//~^ ERROR `...` range patterns are deprecated
|
||||
if let true... = 0 {} //~ ERROR `X...` range patterns are not supported
|
||||
//~^ ERROR `...` range patterns are deprecated
|
||||
//~| ERROR only char and numeric types
|
||||
if let .0... = 0 {} //~ ERROR `X...` range patterns are not supported
|
||||
//~^ ERROR float literals must have an integer part
|
||||
//~| ERROR `...` range patterns are deprecated
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn exclusive_to() {
|
||||
if let ..0 = 0 {} //~ ERROR `..X` range patterns are not supported
|
||||
if let ..Y = 0 {} //~ ERROR `..X` range patterns are not supported
|
||||
if let ..true = 0 {} //~ ERROR `..X` range patterns are not supported
|
||||
//~| ERROR only char and numeric types
|
||||
if let .. .0 = 0 {} //~ ERROR `..X` range patterns are not supported
|
||||
//~^ ERROR float literals must have an integer part
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn inclusive_to() {
|
||||
if let ..=3 = 0 {} //~ ERROR `..=X` range patterns are not supported
|
||||
if let ..=Y = 0 {} //~ ERROR `..=X` range patterns are not supported
|
||||
if let ..=true = 0 {} //~ ERROR `..=X` range patterns are not supported
|
||||
//~| ERROR only char and numeric types
|
||||
if let ..=.0 = 0 {} //~ ERROR `..=X` range patterns are not supported
|
||||
//~^ ERROR float literals must have an integer part
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn inclusive2_to() {
|
||||
if let ...3 = 0 {} //~ ERROR `...X` range patterns are not supported
|
||||
//~^ ERROR `...` range patterns are deprecated
|
||||
if let ...Y = 0 {} //~ ERROR `...X` range patterns are not supported
|
||||
//~^ ERROR `...` range patterns are deprecated
|
||||
if let ...true = 0 {} //~ ERROR `...X` range patterns are not supported
|
||||
//~^ ERROR `...` range patterns are deprecated
|
||||
//~| ERROR only char and numeric types
|
||||
if let ....3 = 0 {} //~ ERROR `...X` range patterns are not supported
|
||||
//~^ ERROR float literals must have an integer part
|
||||
//~| ERROR `...` range patterns are deprecated
|
||||
//~| ERROR mismatched types
|
||||
}
|
538
src/test/ui/parser/recover-range-pats.stderr
Normal file
538
src/test/ui/parser/recover-range-pats.stderr
Normal file
@ -0,0 +1,538 @@
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:21:12
|
||||
|
|
||||
LL | if let .0..Y = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:23:16
|
||||
|
|
||||
LL | if let X.. .0 = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:34:12
|
||||
|
|
||||
LL | if let .0..=Y = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:36:16
|
||||
|
|
||||
LL | if let X..=.0 = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:49:12
|
||||
|
|
||||
LL | if let .0...Y = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:52:17
|
||||
|
|
||||
LL | if let X... .0 = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: `X..` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:58:12
|
||||
|
|
||||
LL | if let 0.. = 0 {}
|
||||
| ^^^ help: try using the maximum value for the type: `0..MAX`
|
||||
|
||||
error: `X..` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:59:12
|
||||
|
|
||||
LL | if let X.. = 0 {}
|
||||
| ^^^ help: try using the maximum value for the type: `X..MAX`
|
||||
|
||||
error: `X..` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:60:12
|
||||
|
|
||||
LL | if let true.. = 0 {}
|
||||
| ^^^^^^ help: try using the maximum value for the type: `true..MAX`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:62:12
|
||||
|
|
||||
LL | if let .0.. = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: `X..` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:62:12
|
||||
|
|
||||
LL | if let .0.. = 0 {}
|
||||
| ^^^^ help: try using the maximum value for the type: `0.0..MAX`
|
||||
|
||||
error: `X..=` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:68:12
|
||||
|
|
||||
LL | if let 0..= = 0 {}
|
||||
| ^^^^ help: try using the maximum value for the type: `0..=MAX`
|
||||
|
||||
error: `X..=` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:69:12
|
||||
|
|
||||
LL | if let X..= = 0 {}
|
||||
| ^^^^ help: try using the maximum value for the type: `X..=MAX`
|
||||
|
||||
error: `X..=` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:70:12
|
||||
|
|
||||
LL | if let true..= = 0 {}
|
||||
| ^^^^^^^ help: try using the maximum value for the type: `true..=MAX`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:72:12
|
||||
|
|
||||
LL | if let .0..= = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: `X..=` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:72:12
|
||||
|
|
||||
LL | if let .0..= = 0 {}
|
||||
| ^^^^^ help: try using the maximum value for the type: `0.0..=MAX`
|
||||
|
||||
error: `X...` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:78:12
|
||||
|
|
||||
LL | if let 0... = 0 {}
|
||||
| ^^^^ help: try using the maximum value for the type: `0...MAX`
|
||||
|
||||
error: `X...` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:80:12
|
||||
|
|
||||
LL | if let X... = 0 {}
|
||||
| ^^^^ help: try using the maximum value for the type: `X...MAX`
|
||||
|
||||
error: `X...` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:82:12
|
||||
|
|
||||
LL | if let true... = 0 {}
|
||||
| ^^^^^^^ help: try using the maximum value for the type: `true...MAX`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:85:12
|
||||
|
|
||||
LL | if let .0... = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: `X...` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:85:12
|
||||
|
|
||||
LL | if let .0... = 0 {}
|
||||
| ^^^^^ help: try using the maximum value for the type: `0.0...MAX`
|
||||
|
||||
error: `..X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:92:12
|
||||
|
|
||||
LL | if let ..0 = 0 {}
|
||||
| ^^^ help: try using the minimum value for the type: `MIN..0`
|
||||
|
||||
error: `..X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:93:12
|
||||
|
|
||||
LL | if let ..Y = 0 {}
|
||||
| ^^^ help: try using the minimum value for the type: `MIN..Y`
|
||||
|
||||
error: `..X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:94:12
|
||||
|
|
||||
LL | if let ..true = 0 {}
|
||||
| ^^^^^^ help: try using the minimum value for the type: `MIN..true`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:96:15
|
||||
|
|
||||
LL | if let .. .0 = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: `..X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:96:12
|
||||
|
|
||||
LL | if let .. .0 = 0 {}
|
||||
| ^^^^^ help: try using the minimum value for the type: `MIN..0.0`
|
||||
|
||||
error: `..=X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:102:12
|
||||
|
|
||||
LL | if let ..=3 = 0 {}
|
||||
| ^^^^ help: try using the minimum value for the type: `MIN..=3`
|
||||
|
||||
error: `..=X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:103:12
|
||||
|
|
||||
LL | if let ..=Y = 0 {}
|
||||
| ^^^^ help: try using the minimum value for the type: `MIN..=Y`
|
||||
|
||||
error: `..=X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:104:12
|
||||
|
|
||||
LL | if let ..=true = 0 {}
|
||||
| ^^^^^^^ help: try using the minimum value for the type: `MIN..=true`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:106:15
|
||||
|
|
||||
LL | if let ..=.0 = 0 {}
|
||||
| ^^ help: must have an integer part: `0.0`
|
||||
|
||||
error: `..=X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:106:12
|
||||
|
|
||||
LL | if let ..=.0 = 0 {}
|
||||
| ^^^^^ help: try using the minimum value for the type: `MIN..=0.0`
|
||||
|
||||
error: `...X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:112:12
|
||||
|
|
||||
LL | if let ...3 = 0 {}
|
||||
| ^^^^ help: try using the minimum value for the type: `MIN...3`
|
||||
|
||||
error: `...X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:114:12
|
||||
|
|
||||
LL | if let ...Y = 0 {}
|
||||
| ^^^^ help: try using the minimum value for the type: `MIN...Y`
|
||||
|
||||
error: `...X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:116:12
|
||||
|
|
||||
LL | if let ...true = 0 {}
|
||||
| ^^^^^^^ help: try using the minimum value for the type: `MIN...true`
|
||||
|
||||
error: float literals must have an integer part
|
||||
--> $DIR/recover-range-pats.rs:119:15
|
||||
|
|
||||
LL | if let ....3 = 0 {}
|
||||
| ^^ help: must have an integer part: `0.3`
|
||||
|
||||
error: `...X` range patterns are not supported
|
||||
--> $DIR/recover-range-pats.rs:119:12
|
||||
|
|
||||
LL | if let ....3 = 0 {}
|
||||
| ^^^^^ help: try using the minimum value for the type: `MIN...0.3`
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:41:13
|
||||
|
|
||||
LL | if let 0...3 = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/recover-range-pats.rs:7:9
|
||||
|
|
||||
LL | #![deny(ellipsis_inclusive_range_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:42:13
|
||||
|
|
||||
LL | if let 0...Y = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:43:13
|
||||
|
|
||||
LL | if let X...3 = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:44:13
|
||||
|
|
||||
LL | if let X...Y = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:45:16
|
||||
|
|
||||
LL | if let true...Y = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:47:13
|
||||
|
|
||||
LL | if let X...true = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:49:14
|
||||
|
|
||||
LL | if let .0...Y = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:52:13
|
||||
|
|
||||
LL | if let X... .0 = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:78:13
|
||||
|
|
||||
LL | if let 0... = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:80:13
|
||||
|
|
||||
LL | if let X... = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:82:16
|
||||
|
|
||||
LL | if let true... = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:85:14
|
||||
|
|
||||
LL | if let .0... = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:112:12
|
||||
|
|
||||
LL | if let ...3 = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:114:12
|
||||
|
|
||||
LL | if let ...Y = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:116:12
|
||||
|
|
||||
LL | if let ...true = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/recover-range-pats.rs:119:12
|
||||
|
|
||||
LL | if let ....3 = 0 {}
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:19:12
|
||||
|
|
||||
LL | if let true..Y = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: bool
|
||||
= note: end type: u8
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:20:15
|
||||
|
|
||||
LL | if let X..true = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: u8
|
||||
= note: end type: bool
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:21:12
|
||||
|
|
||||
LL | if let .0..Y = 0 {}
|
||||
| ^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found type `{float}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:23:12
|
||||
|
|
||||
LL | if let X.. .0 = 0 {}
|
||||
| ^^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `u8`
|
||||
found type `{float}`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:32:12
|
||||
|
|
||||
LL | if let true..=Y = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: bool
|
||||
= note: end type: u8
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:33:16
|
||||
|
|
||||
LL | if let X..=true = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: u8
|
||||
= note: end type: bool
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:34:12
|
||||
|
|
||||
LL | if let .0..=Y = 0 {}
|
||||
| ^^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found type `{float}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:36:12
|
||||
|
|
||||
LL | if let X..=.0 = 0 {}
|
||||
| ^^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `u8`
|
||||
found type `{float}`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:45:12
|
||||
|
|
||||
LL | if let true...Y = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: bool
|
||||
= note: end type: u8
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:47:16
|
||||
|
|
||||
LL | if let X...true = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: u8
|
||||
= note: end type: bool
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:49:12
|
||||
|
|
||||
LL | if let .0...Y = 0 {}
|
||||
| ^^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found type `{float}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:52:12
|
||||
|
|
||||
LL | if let X... .0 = 0 {}
|
||||
| ^^^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `u8`
|
||||
found type `{float}`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:60:12
|
||||
|
|
||||
LL | if let true.. = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: bool
|
||||
= note: end type: [type error]
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:62:12
|
||||
|
|
||||
LL | if let .0.. = 0 {}
|
||||
| ^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found type `{float}`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:70:12
|
||||
|
|
||||
LL | if let true..= = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: bool
|
||||
= note: end type: [type error]
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:72:12
|
||||
|
|
||||
LL | if let .0..= = 0 {}
|
||||
| ^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found type `{float}`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:82:12
|
||||
|
|
||||
LL | if let true... = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: bool
|
||||
= note: end type: [type error]
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:85:12
|
||||
|
|
||||
LL | if let .0... = 0 {}
|
||||
| ^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found type `{float}`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:94:14
|
||||
|
|
||||
LL | if let ..true = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: [type error]
|
||||
= note: end type: bool
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:96:12
|
||||
|
|
||||
LL | if let .. .0 = 0 {}
|
||||
| ^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found type `{float}`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:104:15
|
||||
|
|
||||
LL | if let ..=true = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: [type error]
|
||||
= note: end type: bool
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:106:12
|
||||
|
|
||||
LL | if let ..=.0 = 0 {}
|
||||
| ^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found type `{float}`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
--> $DIR/recover-range-pats.rs:116:15
|
||||
|
|
||||
LL | if let ...true = 0 {}
|
||||
| ^^^^ ranges require char or numeric types
|
||||
|
|
||||
= note: start type: [type error]
|
||||
= note: end type: bool
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-range-pats.rs:119:12
|
||||
|
|
||||
LL | if let ....3 = 0 {}
|
||||
| ^^^^^ expected integer, found floating-point number
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found type `{float}`
|
||||
|
||||
error: aborting due to 76 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0029, E0308.
|
||||
For more information about an error, try `rustc --explain E0029`.
|
@ -1,12 +1,12 @@
|
||||
// NOTE: This doesn't recover anymore.
|
||||
|
||||
fn main() {
|
||||
let x = (1, 2, 3, 4);
|
||||
match x {
|
||||
(1, .., 4) => {}
|
||||
(1, .=., 4) => { let _: usize = ""; }
|
||||
//~^ ERROR expected pattern, found `.`
|
||||
//~| ERROR mismatched types
|
||||
(.=., 4) => {}
|
||||
//~^ ERROR expected pattern, found `.`
|
||||
(1, 2, 3, 4) => {}
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,8 @@
|
||||
error: expected pattern, found `.`
|
||||
--> $DIR/recover-tuple-pat.rs:5:13
|
||||
--> $DIR/recover-tuple-pat.rs:7:13
|
||||
|
|
||||
LL | (1, .=., 4) => { let _: usize = ""; }
|
||||
| ^ expected pattern
|
||||
|
||||
error: expected pattern, found `.`
|
||||
--> $DIR/recover-tuple-pat.rs:8:10
|
||||
|
|
||||
LL | (.=., 4) => {}
|
||||
| ^ expected pattern
|
||||
error: aborting due to previous error
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-tuple-pat.rs:5:41
|
||||
|
|
||||
LL | (1, .=., 4) => { let _: usize = ""; }
|
||||
| ^^ expected usize, found reference
|
||||
|
|
||||
= note: expected type `usize`
|
||||
found type `&'static str`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -4,6 +4,6 @@ pub fn main() {
|
||||
let sl: &[u8] = b"foo";
|
||||
|
||||
match sl { //~ ERROR non-exhaustive patterns
|
||||
[first, remainder..] => {},
|
||||
[first, remainder @ ..] => {},
|
||||
};
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ fn slice_pat() {
|
||||
let sl: &[u8] = b"foo";
|
||||
|
||||
match sl {
|
||||
[first, remainder..] => {
|
||||
[first, remainder @ ..] => {
|
||||
let _: &u8 = first;
|
||||
assert_eq!(first, &b'f');
|
||||
assert_eq!(remainder, b"oo");
|
||||
|
@ -25,7 +25,7 @@ pub fn main() {
|
||||
let (_, _,) = (1, 1,);
|
||||
let [_, _,] = [1, 1,];
|
||||
let [_, _, .., _,] = [1, 1, 1, 1,];
|
||||
let [_, _, _.., _,] = [1, 1, 1, 1,];
|
||||
let [_, _, _, ..,] = [1, 1, 1, 1,];
|
||||
|
||||
let x: Foo<isize,> = Foo::<isize,>(1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user