mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-01 19:23:50 +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 {
|
fn is_symmetric(list: &[u32]) -> bool {
|
||||||
match list {
|
match list {
|
||||||
&[] | &[_] => true,
|
&[] | &[_] => true,
|
||||||
&[x, ref inside.., y] if x == y => is_symmetric(inside),
|
&[x, ref inside @ .., y] if x == y => is_symmetric(inside),
|
||||||
&[..] => false,
|
&[..] => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ use std::mem;
|
|||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
use syntax::ptr::P as AstP;
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
use syntax::errors;
|
use syntax::errors;
|
||||||
use syntax::ext::hygiene::ExpnId;
|
use syntax::ext::hygiene::ExpnId;
|
||||||
@ -467,7 +468,7 @@ impl<'a> LoweringContext<'a> {
|
|||||||
fn visit_pat(&mut self, p: &'tcx Pat) {
|
fn visit_pat(&mut self, p: &'tcx Pat) {
|
||||||
match p.node {
|
match p.node {
|
||||||
// Doesn't generate a HIR node
|
// Doesn't generate a HIR node
|
||||||
PatKind::Paren(..) => {},
|
PatKind::Paren(..) | PatKind::Rest => {},
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(owner) = self.hir_id_owner {
|
if let Some(owner) = self.hir_id_owner {
|
||||||
self.lctx.lower_node_id_with_owner(p.id, owner);
|
self.lctx.lower_node_id_with_owner(p.id, owner);
|
||||||
@ -1156,7 +1157,7 @@ impl<'a> LoweringContext<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
capture_clause: CaptureBy,
|
capture_clause: CaptureBy,
|
||||||
closure_node_id: NodeId,
|
closure_node_id: NodeId,
|
||||||
ret_ty: Option<syntax::ptr::P<Ty>>,
|
ret_ty: Option<AstP<Ty>>,
|
||||||
span: Span,
|
span: Span,
|
||||||
body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
|
body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
|
||||||
) -> hir::ExprKind {
|
) -> hir::ExprKind {
|
||||||
@ -4171,33 +4172,11 @@ impl<'a> LoweringContext<'a> {
|
|||||||
let node = match p.node {
|
let node = match p.node {
|
||||||
PatKind::Wild => hir::PatKind::Wild,
|
PatKind::Wild => hir::PatKind::Wild,
|
||||||
PatKind::Ident(ref binding_mode, ident, ref sub) => {
|
PatKind::Ident(ref binding_mode, ident, ref sub) => {
|
||||||
match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
|
let lower_sub = |this: &mut Self| sub.as_ref().map(|x| this.lower_pat(x));
|
||||||
// `None` can occur in body-less function signatures
|
self.lower_pat_ident(p, binding_mode, ident, lower_sub)
|
||||||
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)],
|
|
||||||
}),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
|
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(
|
let qpath = self.lower_qpath(
|
||||||
p.id,
|
p.id,
|
||||||
&None,
|
&None,
|
||||||
@ -4205,11 +4184,8 @@ impl<'a> LoweringContext<'a> {
|
|||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
ImplTraitContext::disallowed(),
|
ImplTraitContext::disallowed(),
|
||||||
);
|
);
|
||||||
hir::PatKind::TupleStruct(
|
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
|
||||||
qpath,
|
hir::PatKind::TupleStruct(qpath, pats, ddpos)
|
||||||
pats.iter().map(|x| self.lower_pat(x)).collect(),
|
|
||||||
ddpos,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
PatKind::Path(ref qself, ref path) => {
|
PatKind::Path(ref qself, ref path) => {
|
||||||
let qpath = self.lower_qpath(
|
let qpath = self.lower_qpath(
|
||||||
@ -4246,8 +4222,9 @@ impl<'a> LoweringContext<'a> {
|
|||||||
.collect();
|
.collect();
|
||||||
hir::PatKind::Struct(qpath, fs, etc)
|
hir::PatKind::Struct(qpath, fs, etc)
|
||||||
}
|
}
|
||||||
PatKind::Tuple(ref elts, ddpos) => {
|
PatKind::Tuple(ref pats) => {
|
||||||
hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
|
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::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
|
||||||
PatKind::Ref(ref inner, mutbl) => {
|
PatKind::Ref(ref inner, mutbl) => {
|
||||||
@ -4258,15 +4235,138 @@ impl<'a> LoweringContext<'a> {
|
|||||||
P(self.lower_expr(e2)),
|
P(self.lower_expr(e2)),
|
||||||
self.lower_range_end(end),
|
self.lower_range_end(end),
|
||||||
),
|
),
|
||||||
PatKind::Slice(ref before, ref slice, ref after) => hir::PatKind::Slice(
|
PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
|
||||||
before.iter().map(|x| self.lower_pat(x)).collect(),
|
PatKind::Rest => {
|
||||||
slice.as_ref().map(|x| self.lower_pat(x)),
|
// If we reach here the `..` pattern is not semantically allowed.
|
||||||
after.iter().map(|x| self.lower_pat(x)).collect(),
|
self.ban_illegal_rest_pat(p.span)
|
||||||
),
|
}
|
||||||
PatKind::Paren(ref inner) => return self.lower_pat(inner),
|
PatKind::Paren(ref inner) => return self.lower_pat(inner),
|
||||||
PatKind::Mac(_) => panic!("Shouldn't exist here"),
|
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 {
|
P(hir::Pat {
|
||||||
hir_id: self.lower_node_id(p.id),
|
hir_id: self.lower_node_id(p.id),
|
||||||
node,
|
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 {
|
fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
|
||||||
match *e {
|
match *e {
|
||||||
RangeEnd::Included(_) => hir::RangeEnd::Included,
|
RangeEnd::Included(_) => hir::RangeEnd::Included,
|
||||||
|
@ -162,7 +162,7 @@ pub enum PatternKind<'tcx> {
|
|||||||
|
|
||||||
/// Matches against a slice, checking the length and extracting elements.
|
/// Matches against a slice, checking the length and extracting elements.
|
||||||
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
|
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
|
||||||
/// e.g., `&[ref xs..]`.
|
/// e.g., `&[ref xs @ ..]`.
|
||||||
Slice {
|
Slice {
|
||||||
prefix: Vec<Pattern<'tcx>>,
|
prefix: Vec<Pattern<'tcx>>,
|
||||||
slice: Option<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) {
|
fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExprKind::Lit(..) => {}
|
ExprKind::Lit(..) | ExprKind::Err => {}
|
||||||
ExprKind::Path(..) if allow_paths => {}
|
ExprKind::Path(..) if allow_paths => {}
|
||||||
ExprKind::Unary(UnOp::Neg, ref inner)
|
ExprKind::Unary(UnOp::Neg, ref inner)
|
||||||
if match inner.node { ExprKind::Lit(_) => true, _ => false } => {}
|
if match inner.node { ExprKind::Lit(_) => true, _ => false } => {}
|
||||||
|
@ -105,20 +105,34 @@ impl TargetDataLayout {
|
|||||||
let mut dl = TargetDataLayout::default();
|
let mut dl = TargetDataLayout::default();
|
||||||
let mut i128_align_src = 64;
|
let mut i128_align_src = 64;
|
||||||
for spec in target.data_layout.split('-') {
|
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::Little,
|
||||||
["E"] => dl.endian = Endian::Big,
|
["E"] => dl.endian = Endian::Big,
|
||||||
[p] if p.starts_with("P") => {
|
[p] if p.starts_with("P") => {
|
||||||
dl.instruction_address_space = parse_address_space(&p[1..], "P")?
|
dl.instruction_address_space = parse_address_space(&p[1..], "P")?
|
||||||
}
|
}
|
||||||
["a", ref a..] => dl.aggregate_align = align(a, "a")?,
|
// FIXME: Ping cfg(bootstrap) -- Use `ref a @ ..` with new bootstrap compiler.
|
||||||
["f32", ref a..] => dl.f32_align = align(a, "f32")?,
|
["a", ..] => {
|
||||||
["f64", ref a..] => dl.f64_align = align(a, "f64")?,
|
let a = &spec_parts[1..]; // FIXME inline into pattern.
|
||||||
[p @ "p", s, ref a..] | [p @ "p0", s, ref a..] => {
|
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_size = size(s, p)?;
|
||||||
dl.pointer_align = align(a, 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>() {
|
let bits = match s[1..].parse::<u64>() {
|
||||||
Ok(bits) => bits,
|
Ok(bits) => bits,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
@ -142,7 +156,8 @@ impl TargetDataLayout {
|
|||||||
dl.i128_align = a;
|
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 v_size = size(&s[1..], "v")?;
|
||||||
let a = align(a, s)?;
|
let a = align(a, s)?;
|
||||||
if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
|
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);
|
let rhs_ty = self.check_expr(end);
|
||||||
|
|
||||||
// Check that both end-points are of numeric or char type.
|
// 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 lhs_compat = numeric_or_char(lhs_ty);
|
||||||
let rhs_compat = numeric_or_char(rhs_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);
|
let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg);
|
||||||
err.span_label(sp, &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 {
|
for variant_span in start {
|
||||||
err.span_label(*variant_span, "");
|
err.span_label(*variant_span, "");
|
||||||
}
|
}
|
||||||
|
@ -3497,8 +3497,8 @@ Example of erroneous code:
|
|||||||
|
|
||||||
let r = &[1, 2];
|
let r = &[1, 2];
|
||||||
match r {
|
match r {
|
||||||
&[a, b, c, rest..] => { // error: pattern requires at least 3
|
&[a, b, c, rest @ ..] => { // error: pattern requires at least 3
|
||||||
// elements but array has 2
|
// elements but array has 2
|
||||||
println!("a={}, b={}, c={} rest={:?}", a, b, c, rest);
|
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];
|
let r = &[1, 2, 3, 4, 5];
|
||||||
match r {
|
match r {
|
||||||
&[a, b, c, rest..] => { // ok!
|
&[a, b, c, rest @ ..] => { // ok!
|
||||||
// prints `a=1, b=2, c=3 rest=[4, 5]`
|
// prints `a=1, b=2, c=3 rest=[4, 5]`
|
||||||
println!("a={}, b={}, c={} rest={:?}", a, b, c, rest);
|
println!("a={}, b={}, c={} rest={:?}", a, b, c, rest);
|
||||||
}
|
}
|
||||||
|
@ -519,21 +519,28 @@ impl fmt::Debug for Pat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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>> {
|
pub(super) fn to_ty(&self) -> Option<P<Ty>> {
|
||||||
let node = match &self.node {
|
let node = match &self.node {
|
||||||
|
// In a type expression `_` is an inference variable.
|
||||||
PatKind::Wild => TyKind::Infer,
|
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) => {
|
PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) => {
|
||||||
TyKind::Path(None, Path::from_ident(*ident))
|
TyKind::Path(None, Path::from_ident(*ident))
|
||||||
}
|
}
|
||||||
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
|
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
|
||||||
PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
|
PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
|
||||||
|
// `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type.
|
||||||
PatKind::Ref(pat, mutbl) => pat
|
PatKind::Ref(pat, mutbl) => pat
|
||||||
.to_ty()
|
.to_ty()
|
||||||
.map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
|
.map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
|
||||||
PatKind::Slice(pats, None, _) if pats.len() == 1 => {
|
// A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
|
||||||
pats[0].to_ty().map(TyKind::Slice)?
|
// when `P` can be reparsed as a type `T`.
|
||||||
}
|
PatKind::Slice(pats) if pats.len() == 1 => pats[0].to_ty().map(TyKind::Slice)?,
|
||||||
PatKind::Tuple(pats, None) => {
|
// 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());
|
let mut tys = Vec::with_capacity(pats.len());
|
||||||
// FIXME(#48994) - could just be collected into an Option<Vec>
|
// FIXME(#48994) - could just be collected into an Option<Vec>
|
||||||
for pat in pats {
|
for pat in pats {
|
||||||
@ -559,19 +566,15 @@ impl Pat {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.node {
|
match &self.node {
|
||||||
PatKind::Ident(_, _, Some(ref p)) => p.walk(it),
|
PatKind::Ident(_, _, Some(p)) => p.walk(it),
|
||||||
PatKind::Struct(_, ref fields, _) => fields.iter().all(|field| field.node.pat.walk(it)),
|
PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.node.pat.walk(it)),
|
||||||
PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
|
PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) => {
|
||||||
s.iter().all(|p| p.walk(it))
|
s.iter().all(|p| p.walk(it))
|
||||||
}
|
}
|
||||||
PatKind::Box(ref s) | PatKind::Ref(ref s, _) | PatKind::Paren(ref s) => s.walk(it),
|
PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(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::Wild
|
PatKind::Wild
|
||||||
|
| PatKind::Rest
|
||||||
| PatKind::Lit(_)
|
| PatKind::Lit(_)
|
||||||
| PatKind::Range(..)
|
| PatKind::Range(..)
|
||||||
| PatKind::Ident(..)
|
| PatKind::Ident(..)
|
||||||
@ -579,6 +582,14 @@ impl Pat {
|
|||||||
| PatKind::Mac(_) => true,
|
| 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
|
/// A single field in a struct pattern
|
||||||
@ -630,9 +641,7 @@ pub enum PatKind {
|
|||||||
Struct(Path, Vec<Spanned<FieldPat>>, /* recovered */ bool),
|
Struct(Path, Vec<Spanned<FieldPat>>, /* recovered */ bool),
|
||||||
|
|
||||||
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
|
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
|
||||||
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
|
TupleStruct(Path, Vec<P<Pat>>),
|
||||||
/// `0 <= position <= subpats.len()`.
|
|
||||||
TupleStruct(Path, Vec<P<Pat>>, Option<usize>),
|
|
||||||
|
|
||||||
/// A possibly qualified path pattern.
|
/// A possibly qualified path pattern.
|
||||||
/// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
|
/// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
|
||||||
@ -641,9 +650,7 @@ pub enum PatKind {
|
|||||||
Path(Option<QSelf>, Path),
|
Path(Option<QSelf>, Path),
|
||||||
|
|
||||||
/// A tuple pattern (`(a, b)`).
|
/// A tuple pattern (`(a, b)`).
|
||||||
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
|
Tuple(Vec<P<Pat>>),
|
||||||
/// `0 <= position <= subpats.len()`.
|
|
||||||
Tuple(Vec<P<Pat>>, Option<usize>),
|
|
||||||
|
|
||||||
/// A `box` pattern.
|
/// A `box` pattern.
|
||||||
Box(P<Pat>),
|
Box(P<Pat>),
|
||||||
@ -657,9 +664,22 @@ pub enum PatKind {
|
|||||||
/// A range pattern (e.g., `1...2`, `1..=2` or `1..2`).
|
/// A range pattern (e.g., `1...2`, `1..=2` or `1..2`).
|
||||||
Range(P<Expr>, P<Expr>, Spanned<RangeEnd>),
|
Range(P<Expr>, P<Expr>, Spanned<RangeEnd>),
|
||||||
|
|
||||||
/// `[a, b, ..i, y, z]` is represented as:
|
/// A slice pattern `[a, b, c]`.
|
||||||
/// `PatKind::Slice(box [a, b], Some(i), box [y, z])`
|
Slice(Vec<P<Pat>>),
|
||||||
Slice(Vec<P<Pat>>, Option<P<Pat>>, 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)`).
|
/// Parentheses in patterns used for grouping (i.e., `(PAT)`).
|
||||||
Paren(P<Pat>),
|
Paren(P<Pat>),
|
||||||
|
@ -840,14 +840,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||||||
}
|
}
|
||||||
fn pat_tuple_struct(&self, span: Span, path: ast::Path,
|
fn pat_tuple_struct(&self, span: Span, path: ast::Path,
|
||||||
subpats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
|
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,
|
fn pat_struct(&self, span: Span, path: ast::Path,
|
||||||
field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> {
|
field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> {
|
||||||
self.pat(span, PatKind::Struct(path, field_pats, false))
|
self.pat(span, PatKind::Struct(path, field_pats, false))
|
||||||
}
|
}
|
||||||
fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
|
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> {
|
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) {
|
fn visit_pat(&mut self, pattern: &'a ast::Pat) {
|
||||||
match pattern.node {
|
match &pattern.node {
|
||||||
PatKind::Slice(_, Some(ref subslice), _) => {
|
PatKind::Slice(pats) => {
|
||||||
gate_feature_post!(&self, slice_patterns,
|
for pat in &*pats {
|
||||||
subslice.span,
|
let span = pat.span;
|
||||||
"syntax for subslices in slice patterns is not yet stabilized");
|
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(..) => {
|
PatKind::Box(..) => {
|
||||||
gate_feature_post!(&self, box_patterns,
|
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();
|
let Pat { id, node, span } = pat.deref_mut();
|
||||||
vis.visit_id(id);
|
vis.visit_id(id);
|
||||||
match node {
|
match node {
|
||||||
PatKind::Wild => {}
|
PatKind::Wild | PatKind::Rest => {}
|
||||||
PatKind::Ident(_binding_mode, ident, sub) => {
|
PatKind::Ident(_binding_mode, ident, sub) => {
|
||||||
vis.visit_ident(ident);
|
vis.visit_ident(ident);
|
||||||
visit_opt(sub, |sub| vis.visit_pat(sub));
|
visit_opt(sub, |sub| vis.visit_pat(sub));
|
||||||
}
|
}
|
||||||
PatKind::Lit(e) => vis.visit_expr(e),
|
PatKind::Lit(e) => vis.visit_expr(e),
|
||||||
PatKind::TupleStruct(path, pats, _ddpos) => {
|
PatKind::TupleStruct(path, elems) => {
|
||||||
vis.visit_path(path);
|
vis.visit_path(path);
|
||||||
visit_vec(pats, |pat| vis.visit_pat(pat));
|
visit_vec(elems, |elem| vis.visit_pat(elem));
|
||||||
}
|
}
|
||||||
PatKind::Path(qself, path) => {
|
PatKind::Path(qself, path) => {
|
||||||
vis.visit_qself(qself);
|
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);
|
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::Box(inner) => vis.visit_pat(inner),
|
||||||
PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
|
PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
|
||||||
PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
|
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_expr(e2);
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
}
|
}
|
||||||
PatKind::Slice(before, slice, after) => {
|
PatKind::Slice(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)),
|
||||||
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::Paren(inner) => vis.visit_pat(inner),
|
PatKind::Paren(inner) => vis.visit_pat(inner),
|
||||||
PatKind::Mac(mac) => vis.visit_mac(mac),
|
PatKind::Mac(mac) => vis.visit_mac(mac),
|
||||||
}
|
}
|
||||||
|
@ -890,14 +890,13 @@ impl<'a> Parser<'a> {
|
|||||||
/// Parses a sequence, including the closing delimiter. The function
|
/// Parses a sequence, including the closing delimiter. The function
|
||||||
/// `f` must consume tokens until reaching the next separator or
|
/// `f` must consume tokens until reaching the next separator or
|
||||||
/// closing bracket.
|
/// closing bracket.
|
||||||
pub fn parse_seq_to_end<T, F>(&mut self,
|
pub fn parse_seq_to_end<T>(
|
||||||
ket: &TokenKind,
|
&mut self,
|
||||||
sep: SeqSep,
|
ket: &TokenKind,
|
||||||
f: F)
|
sep: SeqSep,
|
||||||
-> PResult<'a, Vec<T>> where
|
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||||
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
) -> PResult<'a, Vec<T>> {
|
||||||
{
|
let (val, _, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
|
||||||
let (val, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
|
|
||||||
if !recovered {
|
if !recovered {
|
||||||
self.bump();
|
self.bump();
|
||||||
}
|
}
|
||||||
@ -907,39 +906,39 @@ impl<'a> Parser<'a> {
|
|||||||
/// Parses a sequence, not including the closing delimiter. The function
|
/// Parses a sequence, not including the closing delimiter. The function
|
||||||
/// `f` must consume tokens until reaching the next separator or
|
/// `f` must consume tokens until reaching the next separator or
|
||||||
/// closing bracket.
|
/// closing bracket.
|
||||||
pub fn parse_seq_to_before_end<T, F>(
|
pub fn parse_seq_to_before_end<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
ket: &TokenKind,
|
ket: &TokenKind,
|
||||||
sep: SeqSep,
|
sep: SeqSep,
|
||||||
f: F,
|
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||||
) -> PResult<'a, (Vec<T>, bool)>
|
) -> PResult<'a, (Vec<T>, bool, bool)> {
|
||||||
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
|
|
||||||
{
|
|
||||||
self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
|
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,
|
&mut self,
|
||||||
kets: &[&TokenKind],
|
kets: &[&TokenKind],
|
||||||
sep: SeqSep,
|
sep: SeqSep,
|
||||||
expect: TokenExpectType,
|
expect: TokenExpectType,
|
||||||
mut f: F,
|
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||||
) -> PResult<'a, (Vec<T>, bool /* recovered */)>
|
) -> PResult<'a, (Vec<T>, bool /* trailing */, bool /* recovered */)> {
|
||||||
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
|
|
||||||
{
|
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
let mut recovered = false;
|
let mut recovered = false;
|
||||||
|
let mut trailing = false;
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
while !kets.iter().any(|k| {
|
while !self.expect_any_with_type(kets, expect) {
|
||||||
match expect {
|
if let token::CloseDelim(..) | token::Eof = self.token.kind {
|
||||||
TokenExpectType::Expect => self.check(k),
|
break
|
||||||
TokenExpectType::NoExpect => self.token == **k,
|
}
|
||||||
}
|
|
||||||
}) {
|
|
||||||
match self.token.kind {
|
|
||||||
token::CloseDelim(..) | token::Eof => break,
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
if let Some(ref t) = sep.sep {
|
if let Some(ref t) = sep.sep {
|
||||||
if first {
|
if first {
|
||||||
first = false;
|
first = false;
|
||||||
@ -973,12 +972,8 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sep.trailing_sep_allowed && kets.iter().any(|k| {
|
if sep.trailing_sep_allowed && self.expect_any_with_type(kets, expect) {
|
||||||
match expect {
|
trailing = true;
|
||||||
TokenExpectType::Expect => self.check(k),
|
|
||||||
TokenExpectType::NoExpect => self.token == **k,
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -986,27 +981,45 @@ impl<'a> Parser<'a> {
|
|||||||
v.push(t);
|
v.push(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((v, recovered))
|
Ok((v, trailing, recovered))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a sequence, including the closing delimiter. The function
|
/// Parses a sequence, including the closing delimiter. The function
|
||||||
/// `f` must consume tokens until reaching the next separator or
|
/// `f` must consume tokens until reaching the next separator or
|
||||||
/// closing bracket.
|
/// closing bracket.
|
||||||
fn parse_unspanned_seq<T, F>(
|
fn parse_unspanned_seq<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
bra: &TokenKind,
|
bra: &TokenKind,
|
||||||
ket: &TokenKind,
|
ket: &TokenKind,
|
||||||
sep: SeqSep,
|
sep: SeqSep,
|
||||||
f: F,
|
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||||
) -> PResult<'a, Vec<T>> where
|
) -> PResult<'a, (Vec<T>, bool)> {
|
||||||
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
|
||||||
{
|
|
||||||
self.expect(bra)?;
|
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 {
|
if !recovered {
|
||||||
self.eat(ket);
|
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
|
/// Advance the parser by one token
|
||||||
@ -1804,15 +1817,7 @@ impl<'a> Parser<'a> {
|
|||||||
AngleBracketedArgs { args, constraints, span }.into()
|
AngleBracketedArgs { args, constraints, span }.into()
|
||||||
} else {
|
} else {
|
||||||
// `(T, U) -> R`
|
// `(T, U) -> R`
|
||||||
self.bump(); // `(`
|
let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
|
||||||
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 span = lo.to(self.prev_span);
|
let span = lo.to(self.prev_span);
|
||||||
let output = if self.eat(&token::RArrow) {
|
let output = if self.eat(&token::RArrow) {
|
||||||
Some(self.parse_ty_common(false, false, false)?)
|
Some(self.parse_ty_common(false, false, false)?)
|
||||||
@ -2516,12 +2521,7 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(match self.token.kind {
|
Ok(match self.token.kind {
|
||||||
token::OpenDelim(token::Paren) => {
|
token::OpenDelim(token::Paren) => {
|
||||||
// Method call `expr.f()`
|
// Method call `expr.f()`
|
||||||
let mut args = self.parse_unspanned_seq(
|
let mut args = self.parse_paren_expr_seq()?;
|
||||||
&token::OpenDelim(token::Paren),
|
|
||||||
&token::CloseDelim(token::Paren),
|
|
||||||
SeqSep::trailing_allowed(token::Comma),
|
|
||||||
|p| Ok(p.parse_expr()?)
|
|
||||||
)?;
|
|
||||||
args.insert(0, self_arg);
|
args.insert(0, self_arg);
|
||||||
|
|
||||||
let span = lo.to(self.prev_span);
|
let span = lo.to(self.prev_span);
|
||||||
@ -2606,12 +2606,7 @@ impl<'a> Parser<'a> {
|
|||||||
match self.token.kind {
|
match self.token.kind {
|
||||||
// expr(...)
|
// expr(...)
|
||||||
token::OpenDelim(token::Paren) => {
|
token::OpenDelim(token::Paren) => {
|
||||||
let seq = self.parse_unspanned_seq(
|
let seq = self.parse_paren_expr_seq().map(|es| {
|
||||||
&token::OpenDelim(token::Paren),
|
|
||||||
&token::CloseDelim(token::Paren),
|
|
||||||
SeqSep::trailing_allowed(token::Comma),
|
|
||||||
|p| Ok(p.parse_expr()?)
|
|
||||||
).map(|es| {
|
|
||||||
let nd = self.mk_call(e, es);
|
let nd = self.mk_call(e, es);
|
||||||
let hi = self.prev_span;
|
let hi = self.prev_span;
|
||||||
self.mk_expr(lo.to(hi), nd, ThinVec::new())
|
self.mk_expr(lo.to(hi), nd, ThinVec::new())
|
||||||
@ -2635,6 +2630,10 @@ impl<'a> Parser<'a> {
|
|||||||
return Ok(e);
|
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) {
|
crate fn process_potential_macro_variable(&mut self) {
|
||||||
self.token = match self.token.kind {
|
self.token = match self.token.kind {
|
||||||
token::Dollar if self.token.span.ctxt() != SyntaxContext::empty() &&
|
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(
|
fn parse_pat_field(
|
||||||
&mut self,
|
&mut self,
|
||||||
lo: Span,
|
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
|
/// Is the current token suitable as the start of a range patterns end?
|
||||||
// something more complex like range patterns
|
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 {
|
fn parse_as_ident(&mut self) -> bool {
|
||||||
self.look_ahead(1, |t| match t.kind {
|
self.look_ahead(1, |t| match t.kind {
|
||||||
token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
|
token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
|
||||||
token::DotDotDot | token::DotDotEq | token::ModSep | token::Not => Some(false),
|
token::DotDotDot | token::DotDotEq | token::DotDot |
|
||||||
// ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the
|
token::ModSep | token::Not => false,
|
||||||
// range pattern branch
|
_ => true,
|
||||||
token::DotDot => None,
|
})
|
||||||
_ => Some(true),
|
}
|
||||||
}).unwrap_or_else(|| self.look_ahead(2, |t| match t.kind {
|
|
||||||
token::Comma | token::CloseDelim(token::Bracket) => true,
|
/// Parse and throw away a parentesized comma separated
|
||||||
_ => false,
|
/// 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
|
/// A wrapper around `parse_pat` with some special error handling for the
|
||||||
@ -3876,7 +3773,7 @@ impl<'a> Parser<'a> {
|
|||||||
// later.
|
// later.
|
||||||
let comma_span = self.token.span;
|
let comma_span = self.token.span;
|
||||||
self.bump();
|
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
|
// We didn't expect this to work anyway; we just wanted
|
||||||
// to advance to the end of the comma-sequence so we know
|
// to advance to the end of the comma-sequence so we know
|
||||||
// the span to suggest parenthesizing
|
// the span to suggest parenthesizing
|
||||||
@ -3908,6 +3805,53 @@ impl<'a> Parser<'a> {
|
|||||||
self.parse_pat_with_range_pat(true, expected)
|
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
|
/// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
|
||||||
/// allowed).
|
/// allowed).
|
||||||
fn parse_pat_with_range_pat(
|
fn parse_pat_with_range_pat(
|
||||||
@ -3934,20 +3878,41 @@ impl<'a> Parser<'a> {
|
|||||||
pat = PatKind::Ref(subpat, mutbl);
|
pat = PatKind::Ref(subpat, mutbl);
|
||||||
}
|
}
|
||||||
token::OpenDelim(token::Paren) => {
|
token::OpenDelim(token::Paren) => {
|
||||||
// Parse (pat,pat,pat,...) as tuple pattern
|
// Parse a tuple or parenthesis pattern.
|
||||||
let (fields, ddpos, trailing_comma) = self.parse_parenthesized_pat_list()?;
|
let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
|
||||||
pat = if fields.len() == 1 && ddpos.is_none() && !trailing_comma {
|
|
||||||
|
// 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())
|
PatKind::Paren(fields.into_iter().nth(0).unwrap())
|
||||||
} else {
|
} else {
|
||||||
PatKind::Tuple(fields, ddpos)
|
PatKind::Tuple(fields)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
token::OpenDelim(token::Bracket) => {
|
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();
|
self.bump();
|
||||||
let (before, slice, after) = self.parse_pat_vec_elements()?;
|
pat = if self.is_pat_range_end_start() {
|
||||||
self.expect(&token::CloseDelim(token::Bracket))?;
|
// Parse `..42` for recovery.
|
||||||
pat = PatKind::Slice(before, slice, after);
|
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 != &, &&, (, [
|
// At this point, token != &, &&, (, [
|
||||||
_ => if self.eat_keyword(kw::Underscore) {
|
_ => if self.eat_keyword(kw::Underscore) {
|
||||||
@ -4004,10 +3969,10 @@ impl<'a> Parser<'a> {
|
|||||||
pat = PatKind::Mac(mac);
|
pat = PatKind::Mac(mac);
|
||||||
}
|
}
|
||||||
token::DotDotDot | token::DotDotEq | token::DotDot => {
|
token::DotDotDot | token::DotDotEq | token::DotDot => {
|
||||||
let end_kind = match self.token.kind {
|
let (end_kind, form) = match self.token.kind {
|
||||||
token::DotDot => RangeEnd::Excluded,
|
token::DotDot => (RangeEnd::Excluded, ".."),
|
||||||
token::DotDotDot => RangeEnd::Included(RangeSyntax::DotDotDot),
|
token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."),
|
||||||
token::DotDotEq => RangeEnd::Included(RangeSyntax::DotDotEq),
|
token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="),
|
||||||
_ => panic!("can only parse `..`/`...`/`..=` for ranges \
|
_ => panic!("can only parse `..`/`...`/`..=` for ranges \
|
||||||
(checked above)"),
|
(checked above)"),
|
||||||
};
|
};
|
||||||
@ -4016,9 +3981,8 @@ impl<'a> Parser<'a> {
|
|||||||
let span = lo.to(self.prev_span);
|
let span = lo.to(self.prev_span);
|
||||||
let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new());
|
let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new());
|
||||||
self.bump();
|
self.bump();
|
||||||
let end = self.parse_pat_range_end()?;
|
let end = self.parse_pat_range_end_opt(&begin, form)?;
|
||||||
let op = Spanned { span: op_span, node: end_kind };
|
pat = PatKind::Range(begin, end, respan(op_span, end_kind));
|
||||||
pat = PatKind::Range(begin, end, op);
|
|
||||||
}
|
}
|
||||||
token::OpenDelim(token::Brace) => {
|
token::OpenDelim(token::Brace) => {
|
||||||
if qself.is_some() {
|
if qself.is_some() {
|
||||||
@ -4045,8 +4009,8 @@ impl<'a> Parser<'a> {
|
|||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
// Parse tuple struct or enum pattern
|
// Parse tuple struct or enum pattern
|
||||||
let (fields, ddpos, _) = self.parse_parenthesized_pat_list()?;
|
let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
|
||||||
pat = PatKind::TupleStruct(path, fields, ddpos)
|
pat = PatKind::TupleStruct(path, fields)
|
||||||
}
|
}
|
||||||
_ => pat = PatKind::Path(qself, path),
|
_ => pat = PatKind::Path(qself, path),
|
||||||
}
|
}
|
||||||
@ -4057,19 +4021,18 @@ impl<'a> Parser<'a> {
|
|||||||
let op_span = self.token.span;
|
let op_span = self.token.span;
|
||||||
if self.check(&token::DotDot) || self.check(&token::DotDotEq) ||
|
if self.check(&token::DotDot) || self.check(&token::DotDotEq) ||
|
||||||
self.check(&token::DotDotDot) {
|
self.check(&token::DotDotDot) {
|
||||||
let end_kind = if self.eat(&token::DotDotDot) {
|
let (end_kind, form) = if self.eat(&token::DotDotDot) {
|
||||||
RangeEnd::Included(RangeSyntax::DotDotDot)
|
(RangeEnd::Included(RangeSyntax::DotDotDot), "...")
|
||||||
} else if self.eat(&token::DotDotEq) {
|
} else if self.eat(&token::DotDotEq) {
|
||||||
RangeEnd::Included(RangeSyntax::DotDotEq)
|
(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")
|
||||||
} else if self.eat(&token::DotDot) {
|
} else if self.eat(&token::DotDot) {
|
||||||
RangeEnd::Excluded
|
(RangeEnd::Excluded, "..")
|
||||||
} else {
|
} else {
|
||||||
panic!("impossible case: we already matched \
|
panic!("impossible case: we already matched \
|
||||||
on a range-operator token")
|
on a range-operator token")
|
||||||
};
|
};
|
||||||
let end = self.parse_pat_range_end()?;
|
let end = self.parse_pat_range_end_opt(&begin, form)?;
|
||||||
let op = Spanned { span: op_span, node: end_kind };
|
pat = PatKind::Range(begin, end, respan(op_span, end_kind))
|
||||||
pat = PatKind::Range(begin, end, op);
|
|
||||||
} else {
|
} else {
|
||||||
pat = PatKind::Lit(begin);
|
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)
|
fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool)
|
||||||
-> PResult<'a, (Vec<Arg> , bool)> {
|
-> PResult<'a, (Vec<Arg> , bool)> {
|
||||||
self.expect(&token::OpenDelim(token::Paren))?;
|
|
||||||
|
|
||||||
let sp = self.token.span;
|
let sp = self.token.span;
|
||||||
let mut c_variadic = false;
|
let mut c_variadic = false;
|
||||||
let (args, recovered): (Vec<Option<Arg>>, bool) =
|
let (args, _): (Vec<Option<Arg>>, _) = self.parse_paren_comma_seq(|p| {
|
||||||
self.parse_seq_to_before_end(
|
let do_not_enforce_named_arguments_for_c_variadic =
|
||||||
&token::CloseDelim(token::Paren),
|
|token: &token::Token| -> bool {
|
||||||
SeqSep::trailing_allowed(token::Comma),
|
if token == &token::DotDotDot {
|
||||||
|p| {
|
false
|
||||||
let do_not_enforce_named_arguments_for_c_variadic =
|
} else {
|
||||||
|token: &token::Token| -> bool {
|
named_args
|
||||||
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))))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
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();
|
let args: Vec<_> = args.into_iter().filter_map(|x| x).collect();
|
||||||
|
|
||||||
@ -5573,7 +5525,7 @@ impl<'a> Parser<'a> {
|
|||||||
(vec![self_arg], false)
|
(vec![self_arg], false)
|
||||||
} else if self.eat(&token::Comma) {
|
} else if self.eat(&token::Comma) {
|
||||||
let mut fn_inputs = vec![self_arg];
|
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)?;
|
&token::CloseDelim(token::Paren), sep, parse_arg_fn)?;
|
||||||
fn_inputs.append(&mut input);
|
fn_inputs.append(&mut input);
|
||||||
(fn_inputs, recovered)
|
(fn_inputs, recovered)
|
||||||
@ -5584,7 +5536,9 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
if !recovered {
|
||||||
@ -6185,26 +6139,20 @@ impl<'a> Parser<'a> {
|
|||||||
fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
|
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;`
|
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
|
||||||
// Unit like structs are handled in parse_item_struct function
|
// Unit like structs are handled in parse_item_struct function
|
||||||
let fields = self.parse_unspanned_seq(
|
self.parse_paren_comma_seq(|p| {
|
||||||
&token::OpenDelim(token::Paren),
|
let attrs = p.parse_outer_attributes()?;
|
||||||
&token::CloseDelim(token::Paren),
|
let lo = p.token.span;
|
||||||
SeqSep::trailing_allowed(token::Comma),
|
let vis = p.parse_visibility(true)?;
|
||||||
|p| {
|
let ty = p.parse_ty()?;
|
||||||
let attrs = p.parse_outer_attributes()?;
|
Ok(StructField {
|
||||||
let lo = p.token.span;
|
span: lo.to(ty.span),
|
||||||
let vis = p.parse_visibility(true)?;
|
vis,
|
||||||
let ty = p.parse_ty()?;
|
ident: None,
|
||||||
Ok(StructField {
|
id: ast::DUMMY_NODE_ID,
|
||||||
span: lo.to(ty.span),
|
ty,
|
||||||
vis,
|
attrs,
|
||||||
ident: None,
|
})
|
||||||
id: ast::DUMMY_NODE_ID,
|
}).map(|(r, _)| r)
|
||||||
ty,
|
|
||||||
attrs,
|
|
||||||
})
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(fields)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a structure field declaration.
|
/// Parses a structure field declaration.
|
||||||
@ -7786,11 +7734,8 @@ impl<'a> Parser<'a> {
|
|||||||
/// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`]
|
/// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`]
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
|
fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
|
||||||
self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
|
self.parse_delim_comma_seq(token::Brace, |p| Ok((p.parse_use_tree()?, ast::DUMMY_NODE_ID)))
|
||||||
&token::CloseDelim(token::Brace),
|
.map(|(r, _)| r)
|
||||||
SeqSep::trailing_allowed(token::Comma), |this| {
|
|
||||||
Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
|
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
|
||||||
|
@ -2368,22 +2368,10 @@ impl<'a> State<'a> {
|
|||||||
self.print_pat(p);
|
self.print_pat(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::TupleStruct(ref path, ref elts, ddpos) => {
|
PatKind::TupleStruct(ref path, ref elts) => {
|
||||||
self.print_path(path, true, 0);
|
self.print_path(path, true, 0);
|
||||||
self.popen();
|
self.popen();
|
||||||
if let Some(ddpos) = ddpos {
|
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
|
||||||
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.pclose();
|
self.pclose();
|
||||||
}
|
}
|
||||||
PatKind::Path(None, ref path) => {
|
PatKind::Path(None, ref path) => {
|
||||||
@ -2415,23 +2403,11 @@ impl<'a> State<'a> {
|
|||||||
self.s.space();
|
self.s.space();
|
||||||
self.s.word("}");
|
self.s.word("}");
|
||||||
}
|
}
|
||||||
PatKind::Tuple(ref elts, ddpos) => {
|
PatKind::Tuple(ref elts) => {
|
||||||
self.popen();
|
self.popen();
|
||||||
if let Some(ddpos) = ddpos {
|
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
|
||||||
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
|
if elts.len() == 1 {
|
||||||
if ddpos != 0 {
|
self.s.word(",");
|
||||||
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.pclose();
|
self.pclose();
|
||||||
}
|
}
|
||||||
@ -2457,26 +2433,12 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
self.print_expr(end);
|
self.print_expr(end);
|
||||||
}
|
}
|
||||||
PatKind::Slice(ref before, ref slice, ref after) => {
|
PatKind::Slice(ref elts) => {
|
||||||
self.s.word("[");
|
self.s.word("[");
|
||||||
self.commasep(Inconsistent,
|
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
|
||||||
&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.s.word("]");
|
self.s.word("]");
|
||||||
}
|
}
|
||||||
|
PatKind::Rest => self.s.word(".."),
|
||||||
PatKind::Paren(ref inner) => {
|
PatKind::Paren(ref inner) => {
|
||||||
self.popen();
|
self.popen();
|
||||||
self.print_pat(inner);
|
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) {
|
pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
|
||||||
match pattern.node {
|
match pattern.node {
|
||||||
PatKind::TupleStruct(ref path, ref children, _) => {
|
PatKind::TupleStruct(ref path, ref elems) => {
|
||||||
visitor.visit_path(path, pattern.id);
|
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) => {
|
PatKind::Path(ref opt_qself, ref path) => {
|
||||||
if let Some(ref qself) = *opt_qself {
|
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)
|
visitor.visit_pat(&field.node.pat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Tuple(ref tuple_elements, _) => {
|
PatKind::Tuple(ref elems) => {
|
||||||
walk_list!(visitor, visit_pat, tuple_elements);
|
walk_list!(visitor, visit_pat, elems);
|
||||||
}
|
}
|
||||||
PatKind::Box(ref subpattern) |
|
PatKind::Box(ref subpattern) |
|
||||||
PatKind::Ref(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(lower_bound);
|
||||||
visitor.visit_expr(upper_bound);
|
visitor.visit_expr(upper_bound);
|
||||||
}
|
}
|
||||||
PatKind::Wild => (),
|
PatKind::Wild | PatKind::Rest => {},
|
||||||
PatKind::Slice(ref prepatterns, ref slice_pattern, ref postpatterns) => {
|
PatKind::Slice(ref elems) => {
|
||||||
walk_list!(visitor, visit_pat, prepatterns);
|
walk_list!(visitor, visit_pat, elems);
|
||||||
walk_list!(visitor, visit_pat, slice_pattern);
|
|
||||||
walk_list!(visitor, visit_pat, postpatterns);
|
|
||||||
}
|
}
|
||||||
PatKind::Mac(ref mac) => visitor.visit_mac(mac),
|
PatKind::Mac(ref mac) => visitor.visit_mac(mac),
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ fn move_out_from_end() {
|
|||||||
|
|
||||||
fn move_out_by_subslice() {
|
fn move_out_by_subslice() {
|
||||||
let a = [box 1, box 2];
|
let a = [box 1, box 2];
|
||||||
let [_y..] = a;
|
let [_y @ ..] = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -11,7 +11,7 @@ fn foldl<T, U, F>(values: &[T],
|
|||||||
U: Clone+Debug, T:Debug,
|
U: Clone+Debug, T:Debug,
|
||||||
F: FnMut(U, &T) -> U,
|
F: FnMut(U, &T) -> U,
|
||||||
{ match values {
|
{ match values {
|
||||||
&[ref head, ref tail..] =>
|
&[ref head, ref tail @ ..] =>
|
||||||
foldl(tail, function(initial, head), function),
|
foldl(tail, function(initial, head), function),
|
||||||
&[] => {
|
&[] => {
|
||||||
// FIXME: call guards
|
// FIXME: call guards
|
||||||
@ -28,7 +28,7 @@ fn foldr<T, U, F>(values: &[T],
|
|||||||
F: FnMut(&T, U) -> U,
|
F: FnMut(&T, U) -> U,
|
||||||
{
|
{
|
||||||
match values {
|
match values {
|
||||||
&[ref head.., ref tail] =>
|
&[ref head @ .., ref tail] =>
|
||||||
foldr(head, function(tail, initial), function),
|
foldr(head, function(tail, initial), function),
|
||||||
&[] => {
|
&[] => {
|
||||||
// FIXME: call guards
|
// FIXME: call guards
|
||||||
|
@ -8,7 +8,7 @@ pub fn main() {
|
|||||||
let x: &[isize] = &[1, 2, 3, 4, 5];
|
let x: &[isize] = &[1, 2, 3, 4, 5];
|
||||||
if !x.is_empty() {
|
if !x.is_empty() {
|
||||||
let el = match x {
|
let el = match x {
|
||||||
&[1, ref tail..] => &tail[0],
|
&[1, ref tail @ ..] => &tail[0],
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
println!("{}", *el);
|
println!("{}", *el);
|
||||||
|
@ -14,7 +14,7 @@ fn a() {
|
|||||||
fn b() {
|
fn b() {
|
||||||
let x = [1, 2, 3];
|
let x = [1, 2, 3];
|
||||||
match x {
|
match x {
|
||||||
[a, b, c..] => {
|
[a, b, c @ ..] => {
|
||||||
assert_eq!(a, 1);
|
assert_eq!(a, 1);
|
||||||
assert_eq!(b, 2);
|
assert_eq!(b, 2);
|
||||||
let expected: &[_] = &[3];
|
let expected: &[_] = &[3];
|
||||||
@ -22,7 +22,7 @@ fn b() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
match x {
|
match x {
|
||||||
[a.., b, c] => {
|
[a @ .., b, c] => {
|
||||||
let expected: &[_] = &[1];
|
let expected: &[_] = &[1];
|
||||||
assert_eq!(a, expected);
|
assert_eq!(a, expected);
|
||||||
assert_eq!(b, 2);
|
assert_eq!(b, 2);
|
||||||
@ -30,7 +30,7 @@ fn b() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
match x {
|
match x {
|
||||||
[a, b.., c] => {
|
[a, b @ .., c] => {
|
||||||
assert_eq!(a, 1);
|
assert_eq!(a, 1);
|
||||||
let expected: &[_] = &[2];
|
let expected: &[_] = &[2];
|
||||||
assert_eq!(b, expected);
|
assert_eq!(b, expected);
|
||||||
@ -50,7 +50,7 @@ fn b() {
|
|||||||
fn b_slice() {
|
fn b_slice() {
|
||||||
let x : &[_] = &[1, 2, 3];
|
let x : &[_] = &[1, 2, 3];
|
||||||
match x {
|
match x {
|
||||||
&[a, b, ref c..] => {
|
&[a, b, ref c @ ..] => {
|
||||||
assert_eq!(a, 1);
|
assert_eq!(a, 1);
|
||||||
assert_eq!(b, 2);
|
assert_eq!(b, 2);
|
||||||
let expected: &[_] = &[3];
|
let expected: &[_] = &[3];
|
||||||
@ -59,7 +59,7 @@ fn b_slice() {
|
|||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
match x {
|
match x {
|
||||||
&[ref a.., b, c] => {
|
&[ref a @ .., b, c] => {
|
||||||
let expected: &[_] = &[1];
|
let expected: &[_] = &[1];
|
||||||
assert_eq!(a, expected);
|
assert_eq!(a, expected);
|
||||||
assert_eq!(b, 2);
|
assert_eq!(b, 2);
|
||||||
@ -68,7 +68,7 @@ fn b_slice() {
|
|||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
match x {
|
match x {
|
||||||
&[a, ref b.., c] => {
|
&[a, ref b @ .., c] => {
|
||||||
assert_eq!(a, 1);
|
assert_eq!(a, 1);
|
||||||
let expected: &[_] = &[2];
|
let expected: &[_] = &[2];
|
||||||
assert_eq!(b, expected);
|
assert_eq!(b, expected);
|
||||||
@ -134,20 +134,6 @@ fn e() {
|
|||||||
assert_eq!(c, 1);
|
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() {
|
pub fn main() {
|
||||||
a();
|
a();
|
||||||
b();
|
b();
|
||||||
@ -155,5 +141,4 @@ pub fn main() {
|
|||||||
c();
|
c();
|
||||||
d();
|
d();
|
||||||
e();
|
e();
|
||||||
f();
|
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,14 @@ pub fn main() {
|
|||||||
Foo { string: "baz" }
|
Foo { string: "baz" }
|
||||||
];
|
];
|
||||||
match x {
|
match x {
|
||||||
[ref first, ref tail..] => {
|
[ref first, ref tail @ ..] => {
|
||||||
assert_eq!(first.string, "foo");
|
assert_eq!(first.string, "foo");
|
||||||
assert_eq!(tail.len(), 2);
|
assert_eq!(tail.len(), 2);
|
||||||
assert_eq!(tail[0].string, "bar");
|
assert_eq!(tail[0].string, "bar");
|
||||||
assert_eq!(tail[1].string, "baz");
|
assert_eq!(tail[1].string, "baz");
|
||||||
|
|
||||||
match *(tail as &[_]) {
|
match *(tail as &[_]) {
|
||||||
[Foo { .. }, _, Foo { .. }, ref _tail..] => {
|
[Foo { .. }, _, Foo { .. }, ref _tail @ ..] => {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
[Foo { string: ref a }, Foo { string: ref b }] => {
|
[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 <<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
|
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
|
<<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
|
| ^ not found in this scope
|
||||||
|
|
||||||
error[E0412]: cannot find type `A` 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;
|
LL | <<A>::B>::C;
|
||||||
| ^ not found in this scope
|
| ^ not found in this scope
|
||||||
|
|
||||||
error[E0029]: only char and numeric types are allowed in range patterns
|
error: aborting due to 5 previous errors
|
||||||
--> $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 6 previous errors
|
For more information about this error, try `rustc --explain E0412`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0029, E0412.
|
|
||||||
For more information about an error, try `rustc --explain E0029`.
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
|
|
||||||
fn foo(s: &[i32]) -> &[i32] {
|
fn foo(s: &[i32]) -> &[i32] {
|
||||||
let &[ref xs..] = s;
|
let &[ref xs @ ..] = s;
|
||||||
xs
|
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
|
// The subslice used to go out of bounds for zero-sized array items, check that this doesn't
|
||||||
// happen anymore
|
// happen anymore
|
||||||
match x {
|
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;
|
LL | let x = &mut v;
|
||||||
| ------ borrow of `v` occurs here
|
| ------ borrow of `v` occurs here
|
||||||
LL | match v {
|
LL | match v {
|
||||||
LL | &[x..] => println!("{:?}", x),
|
LL | &[x @ ..] => println!("{:?}", x),
|
||||||
| ^ use of borrowed `v`
|
| ^^^^^^ use of borrowed `v`
|
||||||
...
|
...
|
||||||
LL | drop(x);
|
LL | drop(x);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
@ -204,8 +204,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
|||||||
LL | let x = &mut v;
|
LL | let x = &mut v;
|
||||||
| ------ borrow of `v` occurs here
|
| ------ borrow of `v` occurs here
|
||||||
...
|
...
|
||||||
LL | &[_, x..] => println!("{:?}", x),
|
LL | &[_, x @ ..] => println!("{:?}", x),
|
||||||
| ^ use of borrowed `v`
|
| ^^^^^^ use of borrowed `v`
|
||||||
...
|
...
|
||||||
LL | drop(x);
|
LL | drop(x);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
@ -216,8 +216,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
|||||||
LL | let x = &mut v;
|
LL | let x = &mut v;
|
||||||
| ------ borrow of `v` occurs here
|
| ------ borrow of `v` occurs here
|
||||||
...
|
...
|
||||||
LL | &[x.., _] => println!("{:?}", x),
|
LL | &[x @ .., _] => println!("{:?}", x),
|
||||||
| ^ use of borrowed `v`
|
| ^^^^^^ use of borrowed `v`
|
||||||
...
|
...
|
||||||
LL | drop(x);
|
LL | drop(x);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
@ -228,8 +228,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
|||||||
LL | let x = &mut v;
|
LL | let x = &mut v;
|
||||||
| ------ borrow of `v` occurs here
|
| ------ borrow of `v` occurs here
|
||||||
...
|
...
|
||||||
LL | &[_, x.., _] => println!("{:?}", x),
|
LL | &[_, x @ .., _] => println!("{:?}", x),
|
||||||
| ^ use of borrowed `v`
|
| ^^^^^^ use of borrowed `v`
|
||||||
...
|
...
|
||||||
LL | drop(x);
|
LL | drop(x);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
|
@ -140,22 +140,22 @@ fn main() {
|
|||||||
let mut v = &[1, 2, 3, 4, 5];
|
let mut v = &[1, 2, 3, 4, 5];
|
||||||
let x = &mut v;
|
let x = &mut v;
|
||||||
match v {
|
match v {
|
||||||
&[x..] => println!("{:?}", x),
|
&[x @ ..] => println!("{:?}", x),
|
||||||
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
||||||
_ => panic!("other case"),
|
_ => panic!("other case"),
|
||||||
}
|
}
|
||||||
match v {
|
match v {
|
||||||
&[_, x..] => println!("{:?}", x),
|
&[_, x @ ..] => println!("{:?}", x),
|
||||||
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
||||||
_ => panic!("other case"),
|
_ => panic!("other case"),
|
||||||
}
|
}
|
||||||
match v {
|
match v {
|
||||||
&[x.., _] => println!("{:?}", x),
|
&[x @ .., _] => println!("{:?}", x),
|
||||||
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
||||||
_ => panic!("other case"),
|
_ => panic!("other case"),
|
||||||
}
|
}
|
||||||
match v {
|
match v {
|
||||||
&[_, x.., _] => println!("{:?}", x),
|
&[_, x @ .., _] => println!("{:?}", x),
|
||||||
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
//~^ ERROR cannot use `v[..]` because it was mutably borrowed
|
||||||
_ => panic!("other case"),
|
_ => panic!("other case"),
|
||||||
}
|
}
|
||||||
|
@ -192,8 +192,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
|||||||
LL | let x = &mut v;
|
LL | let x = &mut v;
|
||||||
| ------ borrow of `v` occurs here
|
| ------ borrow of `v` occurs here
|
||||||
LL | match v {
|
LL | match v {
|
||||||
LL | &[x..] => println!("{:?}", x),
|
LL | &[x @ ..] => println!("{:?}", x),
|
||||||
| ^ use of borrowed `v`
|
| ^^^^^^ use of borrowed `v`
|
||||||
...
|
...
|
||||||
LL | drop(x);
|
LL | drop(x);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
@ -204,8 +204,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
|||||||
LL | let x = &mut v;
|
LL | let x = &mut v;
|
||||||
| ------ borrow of `v` occurs here
|
| ------ borrow of `v` occurs here
|
||||||
...
|
...
|
||||||
LL | &[_, x..] => println!("{:?}", x),
|
LL | &[_, x @ ..] => println!("{:?}", x),
|
||||||
| ^ use of borrowed `v`
|
| ^^^^^^ use of borrowed `v`
|
||||||
...
|
...
|
||||||
LL | drop(x);
|
LL | drop(x);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
@ -216,8 +216,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
|||||||
LL | let x = &mut v;
|
LL | let x = &mut v;
|
||||||
| ------ borrow of `v` occurs here
|
| ------ borrow of `v` occurs here
|
||||||
...
|
...
|
||||||
LL | &[x.., _] => println!("{:?}", x),
|
LL | &[x @ .., _] => println!("{:?}", x),
|
||||||
| ^ use of borrowed `v`
|
| ^^^^^^ use of borrowed `v`
|
||||||
...
|
...
|
||||||
LL | drop(x);
|
LL | drop(x);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
@ -228,8 +228,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
|||||||
LL | let x = &mut v;
|
LL | let x = &mut v;
|
||||||
| ------ borrow of `v` occurs here
|
| ------ borrow of `v` occurs here
|
||||||
...
|
...
|
||||||
LL | &[_, x.., _] => println!("{:?}", x),
|
LL | &[_, x @ .., _] => println!("{:?}", x),
|
||||||
| ^ use of borrowed `v`
|
| ^^^^^^ use of borrowed `v`
|
||||||
...
|
...
|
||||||
LL | drop(x);
|
LL | drop(x);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
|
@ -10,7 +10,7 @@ fn move_out_from_begin_and_end() {
|
|||||||
fn move_out_by_const_index_and_subslice() {
|
fn move_out_by_const_index_and_subslice() {
|
||||||
let a = [box 1, box 2];
|
let a = [box 1, box 2];
|
||||||
let [_x, _] = a;
|
let [_x, _] = a;
|
||||||
let [_y..] = a; //~ ERROR [E0382]
|
let [_y @ ..] = a; //~ ERROR [E0382]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -13,8 +13,8 @@ error[E0382]: use of moved value: `a[..]`
|
|||||||
|
|
|
|
||||||
LL | let [_x, _] = a;
|
LL | let [_x, _] = a;
|
||||||
| -- value moved here
|
| -- value moved here
|
||||||
LL | let [_y..] = a;
|
LL | let [_y @ ..] = a;
|
||||||
| ^^ value used here after move
|
| ^^^^^^^ value used here after move
|
||||||
|
|
|
|
||||||
= note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
|
= 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;
|
let x: &[Foo] = &x;
|
||||||
match *x {
|
match *x {
|
||||||
[_, ref tail..] => {
|
[_, ref tail @ ..] => {
|
||||||
match tail {
|
match tail {
|
||||||
//~^ ERROR cannot move out of type `[Foo]`
|
//~^ ERROR cannot move out of type `[Foo]`
|
||||||
&[Foo { string: a },
|
&[Foo { string: a },
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
fn mut_head_tail<'a, A>(v: &'a mut [A]) -> Option<(&'a mut A, &'a mut [A])> {
|
fn mut_head_tail<'a, A>(v: &'a mut [A]) -> Option<(&'a mut A, &'a mut [A])> {
|
||||||
match *v {
|
match *v {
|
||||||
[ref mut head, ref mut tail..] => {
|
[ref mut head, ref mut tail @ ..] => {
|
||||||
Some((head, tail))
|
Some((head, tail))
|
||||||
}
|
}
|
||||||
[] => None
|
[] => None
|
||||||
|
@ -70,7 +70,7 @@ fn const_index_mixed(s: &mut [i32]) {
|
|||||||
|
|
||||||
fn const_index_and_subslice_ok(s: &mut [i32]) {
|
fn const_index_and_subslice_ok(s: &mut [i32]) {
|
||||||
if let [ref first, ref second, ..] = *s {
|
if let [ref first, ref second, ..] = *s {
|
||||||
if let [_, _, ref mut tail..] = *s {
|
if let [_, _, ref mut tail @ ..] = *s {
|
||||||
nop(&[first, second]);
|
nop(&[first, second]);
|
||||||
nop_subslice(tail);
|
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]) {
|
fn const_index_and_subslice_err(s: &mut [i32]) {
|
||||||
if let [ref first, ref second, ..] = *s {
|
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(&[first, second]);
|
||||||
nop_subslice(tail);
|
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]) {
|
fn const_index_and_subslice_from_end_ok(s: &mut [i32]) {
|
||||||
if let [.., ref second, ref first] = *s {
|
if let [.., ref second, ref first] = *s {
|
||||||
if let [ref mut tail.., _, _] = *s {
|
if let [ref mut tail @ .., _, _] = *s {
|
||||||
nop(&[first, second]);
|
nop(&[first, second]);
|
||||||
nop_subslice(tail);
|
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]) {
|
fn const_index_and_subslice_from_end_err(s: &mut [i32]) {
|
||||||
if let [.., ref second, ref first] = *s {
|
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(&[first, second]);
|
||||||
nop_subslice(tail);
|
nop_subslice(tail);
|
||||||
}
|
}
|
||||||
@ -105,8 +105,8 @@ fn const_index_and_subslice_from_end_err(s: &mut [i32]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn subslices(s: &mut [i32]) {
|
fn subslices(s: &mut [i32]) {
|
||||||
if let [_, _, _, ref s1..] = *s {
|
if let [_, _, _, ref s1 @ ..] = *s {
|
||||||
if let [ref mut s2.., _, _, _] = *s { //~ERROR
|
if let [ref mut s2 @ .., _, _, _] = *s { //~ERROR
|
||||||
nop_subslice(s1);
|
nop_subslice(s1);
|
||||||
nop_subslice(s2);
|
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 {
|
LL | if let [ref first, ref second, ..] = *s {
|
||||||
| ---------- immutable borrow occurs here
|
| ---------- immutable borrow occurs here
|
||||||
LL | if let [_, ref mut tail..] = *s {
|
LL | if let [_, ref mut tail @ ..] = *s {
|
||||||
| ^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
LL | nop(&[first, second]);
|
LL | nop(&[first, second]);
|
||||||
| ------ immutable borrow later used here
|
| ------ 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 {
|
LL | if let [.., ref second, ref first] = *s {
|
||||||
| ---------- immutable borrow occurs here
|
| ---------- immutable borrow occurs here
|
||||||
LL | if let [ref mut tail.., _] = *s {
|
LL | if let [ref mut tail @ .., _] = *s {
|
||||||
| ^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
LL | nop(&[first, second]);
|
LL | nop(&[first, second]);
|
||||||
| ------ immutable borrow later used here
|
| ------ immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
|
||||||
--> $DIR/borrowck-slice-pattern-element-loan.rs:109:17
|
--> $DIR/borrowck-slice-pattern-element-loan.rs:109:17
|
||||||
|
|
|
|
||||||
LL | if let [_, _, _, ref s1..] = *s {
|
LL | if let [_, _, _, ref s1 @ ..] = *s {
|
||||||
| ------ immutable borrow occurs here
|
| ----------- immutable borrow occurs here
|
||||||
LL | if let [ref mut s2.., _, _, _] = *s {
|
LL | if let [ref mut s2 @ .., _, _, _] = *s {
|
||||||
| ^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
LL | nop_subslice(s1);
|
LL | nop_subslice(s1);
|
||||||
| -- immutable borrow later used here
|
| -- immutable borrow later used here
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ fn a<'a>() -> &'a [isize] {
|
|||||||
let vec = vec![1, 2, 3, 4];
|
let vec = vec![1, 2, 3, 4];
|
||||||
let vec: &[isize] = &vec;
|
let vec: &[isize] = &vec;
|
||||||
let tail = match vec {
|
let tail = match vec {
|
||||||
&[_, ref tail..] => tail,
|
&[_, ref tail @ ..] => tail,
|
||||||
_ => panic!("a")
|
_ => panic!("a")
|
||||||
};
|
};
|
||||||
tail //~ ERROR cannot return value referencing local variable `vec`
|
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 = vec![1, 2, 3, 4];
|
||||||
let vec: &[isize] = &vec;
|
let vec: &[isize] = &vec;
|
||||||
let init = match vec {
|
let init = match vec {
|
||||||
&[ref init.., _] => init,
|
&[ref init @ .., _] => init,
|
||||||
_ => panic!("b")
|
_ => panic!("b")
|
||||||
};
|
};
|
||||||
init //~ ERROR cannot return value referencing local variable `vec`
|
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 = vec![1, 2, 3, 4];
|
||||||
let vec: &[isize] = &vec;
|
let vec: &[isize] = &vec;
|
||||||
let slice = match vec {
|
let slice = match vec {
|
||||||
&[_, ref slice.., _] => slice,
|
&[_, ref slice @ .., _] => slice,
|
||||||
_ => panic!("c")
|
_ => panic!("c")
|
||||||
};
|
};
|
||||||
slice //~ ERROR cannot return value referencing local variable `vec`
|
slice //~ ERROR cannot return value referencing local variable `vec`
|
||||||
|
@ -4,7 +4,7 @@ fn a() {
|
|||||||
let mut v = vec![1, 2, 3];
|
let mut v = vec![1, 2, 3];
|
||||||
let vb: &mut [isize] = &mut v;
|
let vb: &mut [isize] = &mut v;
|
||||||
match vb {
|
match vb {
|
||||||
&mut [_a, ref tail..] => {
|
&mut [_a, ref tail @ ..] => {
|
||||||
v.push(tail[0] + tail[1]); //~ ERROR cannot borrow
|
v.push(tail[0] + tail[1]); //~ ERROR cannot borrow
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut a = [1, 2, 3, 4];
|
let mut a = [1, 2, 3, 4];
|
||||||
let t = match a {
|
let t = match a {
|
||||||
[1, 2, ref tail..] => tail,
|
[1, 2, ref tail @ ..] => tail,
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
println!("t[0]: {}", t[0]);
|
println!("t[0]: {}", t[0]);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0506]: cannot assign to `a[_]` because it is borrowed
|
error[E0506]: cannot assign to `a[_]` because it is borrowed
|
||||||
--> $DIR/borrowck-vec-pattern-move-tail.rs:12:5
|
--> $DIR/borrowck-vec-pattern-move-tail.rs:12:5
|
||||||
|
|
|
|
||||||
LL | [1, 2, ref tail..] => tail,
|
LL | [1, 2, ref tail @ ..] => tail,
|
||||||
| -------- borrow of `a[_]` occurs here
|
| ------------- borrow of `a[_]` occurs here
|
||||||
...
|
...
|
||||||
LL | a[2] = 0;
|
LL | a[2] = 0;
|
||||||
| ^^^^^^^^ assignment to borrowed `a[_]` occurs here
|
| ^^^^^^^^ assignment to borrowed `a[_]` occurs here
|
||||||
|
@ -19,7 +19,7 @@ fn b() {
|
|||||||
let mut vec = vec![box 1, box 2, box 3];
|
let mut vec = vec![box 1, box 2, box 3];
|
||||||
let vec: &mut [Box<isize>] = &mut vec;
|
let vec: &mut [Box<isize>] = &mut vec;
|
||||||
match vec {
|
match vec {
|
||||||
&mut [ref _b..] => {
|
&mut [ref _b @ ..] => {
|
||||||
//~^ borrow of `vec[_]` occurs here
|
//~^ borrow of `vec[_]` occurs here
|
||||||
vec[0] = box 4; //~ ERROR cannot assign
|
vec[0] = box 4; //~ ERROR cannot assign
|
||||||
//~^ NOTE assignment to borrowed `vec[_]` occurs here
|
//~^ 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
|
error[E0506]: cannot assign to `vec[_]` because it is borrowed
|
||||||
--> $DIR/borrowck-vec-pattern-nesting.rs:24:13
|
--> $DIR/borrowck-vec-pattern-nesting.rs:24:13
|
||||||
|
|
|
|
||||||
LL | &mut [ref _b..] => {
|
LL | &mut [ref _b @ ..] => {
|
||||||
| ------ borrow of `vec[_]` occurs here
|
| ----------- borrow of `vec[_]` occurs here
|
||||||
LL |
|
LL |
|
||||||
LL | vec[0] = box 4;
|
LL | vec[0] = box 4;
|
||||||
| ^^^^^^ assignment to borrowed `vec[_]` occurs here
|
| ^^^^^^ assignment to borrowed `vec[_]` occurs here
|
||||||
|
@ -4,7 +4,7 @@ fn a<'a>() -> &'a isize {
|
|||||||
let vec = vec![1, 2, 3, 4];
|
let vec = vec![1, 2, 3, 4];
|
||||||
let vec: &[isize] = &vec;
|
let vec: &[isize] = &vec;
|
||||||
let tail = match vec {
|
let tail = match vec {
|
||||||
&[_a, ref tail..] => &tail[0],
|
&[_a, ref tail @ ..] => &tail[0],
|
||||||
_ => panic!("foo")
|
_ => panic!("foo")
|
||||||
};
|
};
|
||||||
tail //~ ERROR cannot return value referencing local variable `vec`
|
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 {
|
if arg {
|
||||||
let [.., _x, _] = arr;
|
let [.., _x, _] = arr;
|
||||||
} else {
|
} else {
|
||||||
let [_, _y..] = arr;
|
let [_, _y @ ..] = arr;
|
||||||
}
|
}
|
||||||
a.alloc().await;
|
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 mut ar = [a.alloc().await, a.alloc().await, a.alloc().await];
|
||||||
let [_, _, _x] = ar;
|
let [_, _, _x] = ar;
|
||||||
ar = [a.alloc().await, a.alloc().await, a.alloc().await];
|
ar = [a.alloc().await, a.alloc().await, a.alloc().await];
|
||||||
let [_, _y..] = ar;
|
let [_, _y @ ..] = ar;
|
||||||
a.alloc().await;
|
a.alloc().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ fn subslice_pattern_from_end(a: &Allocator, arg: bool) {
|
|||||||
if arg {
|
if arg {
|
||||||
let[.., _x, _] = a;
|
let[.., _x, _] = a;
|
||||||
} else {
|
} 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 {
|
if arg {
|
||||||
let[.., _x, _] = a;
|
let[.., _x, _] = a;
|
||||||
} else {
|
} 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 mut ar = [a.alloc(), a.alloc(), a.alloc()];
|
||||||
let[_, _, _x] = ar;
|
let[_, _, _x] = ar;
|
||||||
ar = [a.alloc(), a.alloc(), a.alloc()];
|
ar = [a.alloc(), a.alloc(), a.alloc()];
|
||||||
let[_, _y..] = ar;
|
let[_, _y @ ..] = ar;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn panic_after_return(a: &Allocator) -> Ptr<'_> {
|
fn panic_after_return(a: &Allocator) -> Ptr<'_> {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
let r = &[1, 2];
|
let r = &[1, 2];
|
||||||
match r {
|
match r {
|
||||||
&[a, b, c, rest..] => {
|
&[a, b, c, rest @ ..] => {
|
||||||
//~^ ERROR E0528
|
//~^ ERROR E0528
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0528]: pattern requires at least 3 elements but array has 2
|
error[E0528]: pattern requires at least 3 elements but array has 2
|
||||||
--> $DIR/E0528.rs:6:10
|
--> $DIR/E0528.rs:6:10
|
||||||
|
|
|
|
||||||
LL | &[a, b, c, rest..] => {
|
LL | &[a, b, c, rest @ ..] => {
|
||||||
| ^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements
|
| ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match [5..4, 99..105, 43..44] {
|
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: `,`
|
error: `X..` range patterns are not supported
|
||||||
--> $DIR/exclusive_range_pattern_syntax_collision.rs:5:17
|
--> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
|
||||||
|
|
|
|
||||||
LL | [_, 99.., _] => {},
|
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() {
|
fn main() {
|
||||||
match [5..4, 99..105, 43..44] {
|
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: `]`
|
error: `X..` range patterns are not supported
|
||||||
--> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:17
|
--> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
|
||||||
|
|
|
|
||||||
LL | [_, 99..] => {},
|
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() {
|
fn main() {
|
||||||
match [5..4, 99..105, 43..44] {
|
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`
|
error: `..X` range patterns are not supported
|
||||||
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
|
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
|
||||||
|
|
|
|
||||||
LL | [..9, 99..100, _] => {},
|
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() {
|
fn main() {
|
||||||
let x = [1, 2, 3, 4, 5];
|
let x = [1, 2, 3, 4, 5];
|
||||||
match x {
|
match x {
|
||||||
[1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
[1, 2, ..] => {} //~ ERROR subslice patterns are unstable
|
||||||
[1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
[1, .., 5] => {} //~ ERROR subslice patterns are unstable
|
||||||
[.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
[.., 4, 5] => {} //~ ERROR subslice patterns are unstable
|
||||||
}
|
}
|
||||||
|
|
||||||
let x = [ 1, 2, 3, 4, 5 ];
|
let x = [ 1, 2, 3, 4, 5 ];
|
||||||
match x {
|
match x {
|
||||||
[ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
[ xs @ .., 4, 5 ] => {} //~ ERROR subslice patterns are unstable
|
||||||
[ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
[ 1, xs @ .., 5 ] => {} //~ ERROR subslice patterns are unstable
|
||||||
[ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
|
[ 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
|
--> $DIR/feature-gate-slice-patterns.rs:6:16
|
||||||
|
|
|
|
||||||
LL | [1, 2, ..] => {}
|
LL | [1, 2, ..] => {}
|
||||||
@ -7,7 +7,7 @@ LL | [1, 2, ..] => {}
|
|||||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
= 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
|
--> $DIR/feature-gate-slice-patterns.rs:7:13
|
||||||
|
|
|
|
||||||
LL | [1, .., 5] => {}
|
LL | [1, .., 5] => {}
|
||||||
@ -16,7 +16,7 @@ LL | [1, .., 5] => {}
|
|||||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
= 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
|
--> $DIR/feature-gate-slice-patterns.rs:8:10
|
||||||
|
|
|
|
||||||
LL | [.., 4, 5] => {}
|
LL | [.., 4, 5] => {}
|
||||||
@ -25,29 +25,29 @@ LL | [.., 4, 5] => {}
|
|||||||
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
= 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
|
--> $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
|
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
= 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
|
--> $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
|
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
= 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
|
--> $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
|
= note: for more information, see https://github.com/rust-lang/rust/issues/62254
|
||||||
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
|
||||||
|
@ -6,7 +6,7 @@ fn main() {
|
|||||||
let v: isize = match &*sl {
|
let v: isize = match &*sl {
|
||||||
&[] => 0,
|
&[] => 0,
|
||||||
&[a,b,c] => 3,
|
&[a,b,c] => 3,
|
||||||
&[a, ref rest..] => a,
|
&[a, ref rest @ ..] => a,
|
||||||
&[10,a, ref rest..] => 10 //~ ERROR: unreachable pattern
|
&[10,a, ref rest @ ..] => 10 //~ ERROR: unreachable pattern
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/issue-12369.rs:10:9
|
--> $DIR/issue-12369.rs:10:9
|
||||||
|
|
|
|
||||||
LL | &[10,a, ref rest..] => 10
|
LL | &[10,a, ref rest @ ..] => 10
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: lint level defined here
|
note: lint level defined here
|
||||||
--> $DIR/issue-12369.rs:2:9
|
--> $DIR/issue-12369.rs:2:9
|
||||||
|
@ -7,11 +7,11 @@ fn main() {
|
|||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
loop {
|
loop {
|
||||||
x = match *x {
|
x = match *x {
|
||||||
[1, n, 3, ref rest..] => {
|
[1, n, 3, ref rest @ ..] => {
|
||||||
result.push(n);
|
result.push(n);
|
||||||
rest
|
rest
|
||||||
}
|
}
|
||||||
[n, ref rest..] => {
|
[n, ref rest @ ..] => {
|
||||||
result.push(n);
|
result.push(n);
|
||||||
rest
|
rest
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,6 @@ fn count_members(v: &[usize]) -> usize {
|
|||||||
match *v {
|
match *v {
|
||||||
[] => 0,
|
[] => 0,
|
||||||
[_] => 1,
|
[_] => 1,
|
||||||
[_, ref xs..] => 1 + count_members(xs)
|
[_, ref xs @ ..] => 1 + count_members(xs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ fn main() {
|
|||||||
}, 42_usize);
|
}, 42_usize);
|
||||||
|
|
||||||
assert_eq!(match [0u8; 1024] {
|
assert_eq!(match [0u8; 1024] {
|
||||||
[1, _..] => 0_usize,
|
[1, ..] => 0_usize,
|
||||||
[0, _..] => 1_usize,
|
[0, ..] => 1_usize,
|
||||||
_ => 2_usize
|
_ => 2_usize
|
||||||
}, 1_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?)
|
// check-pass
|
||||||
#![allow(dead_code)]
|
|
||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
|
|
||||||
fn check(list: &[u8]) {
|
fn check(list: &[u8]) {
|
||||||
match list {
|
match list {
|
||||||
&[] => {},
|
&[] => {},
|
||||||
&[_u1, _u2, ref _next..] => {},
|
&[_u1, _u2, ref _next @ ..] => {},
|
||||||
&[_u1] => {},
|
&[_u1] => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ fn main() {
|
|||||||
assert_eq!(d, "baz");
|
assert_eq!(d, "baz");
|
||||||
|
|
||||||
let out = bar("baz", "foo");
|
let out = bar("baz", "foo");
|
||||||
let [a, xs.., d] = out;
|
let [a, xs @ .., d] = out;
|
||||||
assert_eq!(a, "baz");
|
assert_eq!(a, "baz");
|
||||||
assert_eq!(xs, ["foo", "foo"]);
|
assert_eq!(xs, ["foo", "foo"]);
|
||||||
assert_eq!(d, "baz");
|
assert_eq!(d, "baz");
|
||||||
|
@ -19,10 +19,10 @@ fn main() {
|
|||||||
match [0, 1, 2] {
|
match [0, 1, 2] {
|
||||||
[0] => {}, //~ ERROR pattern requires
|
[0] => {}, //~ ERROR pattern requires
|
||||||
|
|
||||||
[0, 1, x..] => {
|
[0, 1, x @ ..] => {
|
||||||
let a: [_; 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
|
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
|
error[E0528]: pattern requires at least 4 elements but array has 3
|
||||||
--> $DIR/match-vec-mismatch.rs:25:9
|
--> $DIR/match-vec-mismatch.rs:25:9
|
||||||
|
|
|
|
||||||
LL | [0, 1, 2, 3, x..] => {}
|
LL | [0, 1, 2, 3, x @ ..] => {}
|
||||||
| ^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
|
| ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
|
||||||
|
|
||||||
error[E0282]: type annotations needed
|
error[E0282]: type annotations needed
|
||||||
--> $DIR/match-vec-mismatch.rs:36:9
|
--> $DIR/match-vec-mismatch.rs:36:9
|
||||||
|
@ -23,7 +23,7 @@ fn main() {
|
|||||||
let x: Vec<char> = vec!['a', 'b', 'c'];
|
let x: Vec<char> = vec!['a', 'b', 'c'];
|
||||||
let x: &[char] = &x;
|
let x: &[char] = &x;
|
||||||
match *x {
|
match *x {
|
||||||
['a', 'b', 'c', ref _tail..] => {}
|
['a', 'b', 'c', ref _tail @ ..] => {}
|
||||||
['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
|
['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -32,14 +32,14 @@ fn main() {
|
|||||||
let vec = vec![Some(42), None, Some(21)];
|
let vec = vec![Some(42), None, Some(21)];
|
||||||
let vec: &[Option<isize>] = &vec;
|
let vec: &[Option<isize>] = &vec;
|
||||||
match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered
|
match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered
|
||||||
[Some(..), None, ref tail..] => {}
|
[Some(..), None, ref tail @ ..] => {}
|
||||||
[Some(..), Some(..), ref tail..] => {}
|
[Some(..), Some(..), ref tail @ ..] => {}
|
||||||
[None] => {}
|
[None] => {}
|
||||||
}
|
}
|
||||||
let vec = vec![1];
|
let vec = vec![1];
|
||||||
let vec: &[isize] = &vec;
|
let vec: &[isize] = &vec;
|
||||||
match *vec {
|
match *vec {
|
||||||
[_, ref tail..] => (),
|
[_, ref tail @ ..] => (),
|
||||||
[] => ()
|
[] => ()
|
||||||
}
|
}
|
||||||
let vec = vec![0.5f32];
|
let vec = vec![0.5f32];
|
||||||
@ -53,10 +53,10 @@ fn main() {
|
|||||||
let vec = vec![Some(42), None, Some(21)];
|
let vec = vec![Some(42), None, Some(21)];
|
||||||
let vec: &[Option<isize>] = &vec;
|
let vec: &[Option<isize>] = &vec;
|
||||||
match *vec {
|
match *vec {
|
||||||
[Some(..), None, ref tail..] => {}
|
[Some(..), None, ref tail @ ..] => {}
|
||||||
[Some(..), Some(..), ref tail..] => {}
|
[Some(..), Some(..), ref tail @ ..] => {}
|
||||||
[None, None, ref tail..] => {}
|
[None, None, ref tail @ ..] => {}
|
||||||
[None, Some(..), ref tail..] => {}
|
[None, Some(..), ref tail @ ..] => {}
|
||||||
[Some(_)] => {}
|
[Some(_)] => {}
|
||||||
[None] => {}
|
[None] => {}
|
||||||
[] => {}
|
[] => {}
|
||||||
|
@ -77,7 +77,7 @@ fn vectors_with_nested_enums() {
|
|||||||
[Enum::Second(true), Enum::First] => (),
|
[Enum::Second(true), Enum::First] => (),
|
||||||
[Enum::Second(true), Enum::Second(true)] => (),
|
[Enum::Second(true), Enum::Second(true)] => (),
|
||||||
[Enum::Second(false), _] => (),
|
[Enum::Second(false), _] => (),
|
||||||
[_, _, ref tail.., _] => ()
|
[_, _, ref tail @ .., _] => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
let a = Vec::new();
|
let a: &[u8] = &[];
|
||||||
match a {
|
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 `..`
|
error[E0416]: identifier `tail` is bound more than once in the same pattern
|
||||||
--> $DIR/match-vec-invalid.rs:4:25
|
--> $DIR/match-vec-invalid.rs:4:24
|
||||||
|
|
|
|
||||||
LL | [1, tail.., tail..] => {},
|
LL | [1, tail @ .., tail @ ..] => {},
|
||||||
| ^^ expected one of `,` or `@` here
|
| ^^^^ 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() {
|
fn main() {
|
||||||
|
struct Test(&'static u8, [u8; 0]);
|
||||||
|
let x = Test(&0, []);
|
||||||
|
|
||||||
let Test(&desc[..]) = x; //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
|
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 `[`
|
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;
|
LL | let Test(&desc[..]) = x;
|
||||||
| ^ expected one of `)`, `,`, or `@` here
|
| ^ 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() {
|
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 `[`
|
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
|
| ^ 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() {
|
fn main() {
|
||||||
match (0, 1, 2) {
|
match (0, 1, 2) {
|
||||||
(pat, ..,) => {}
|
(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() {
|
fn main() {
|
||||||
match (0, 1, 2) {
|
match (0, 1, 2) {
|
||||||
(.., pat, ..) => {}
|
(.., 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
|
--> $DIR/pat-tuple-3.rs:3:19
|
||||||
|
|
|
|
||||||
LL | (.., pat, ..) => {}
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
|
const PAT: u8 = 0;
|
||||||
|
|
||||||
match 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`
|
error: `..X` range patterns are not supported
|
||||||
--> $DIR/pat-tuple-4.rs:3:13
|
--> $DIR/pat-tuple-4.rs:5:10
|
||||||
|
|
|
|
||||||
LL | (.. pat) => {}
|
LL | (.. PAT) => {}
|
||||||
| ^^^ expected one of `)` or `,` here
|
| ^^^^^^ 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() {
|
fn main() {
|
||||||
|
const PAT: u8 = 0;
|
||||||
|
|
||||||
match (0, 1) {
|
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: `)`
|
error: `X..` range patterns are not supported
|
||||||
--> $DIR/pat-tuple-5.rs:3:16
|
--> $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() {
|
fn main() {
|
||||||
let x = (1, 2, 3, 4);
|
let x = (1, 2, 3, 4);
|
||||||
match x {
|
match x {
|
||||||
(1, .., 4) => {}
|
(1, .., 4) => {}
|
||||||
(1, .=., 4) => { let _: usize = ""; }
|
(1, .=., 4) => { let _: usize = ""; }
|
||||||
//~^ ERROR expected pattern, found `.`
|
//~^ ERROR expected pattern, found `.`
|
||||||
//~| ERROR mismatched types
|
|
||||||
(.=., 4) => {}
|
(.=., 4) => {}
|
||||||
//~^ ERROR expected pattern, found `.`
|
|
||||||
(1, 2, 3, 4) => {}
|
(1, 2, 3, 4) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,8 @@
|
|||||||
error: expected pattern, found `.`
|
error: expected pattern, found `.`
|
||||||
--> $DIR/recover-tuple-pat.rs:5:13
|
--> $DIR/recover-tuple-pat.rs:7:13
|
||||||
|
|
|
|
||||||
LL | (1, .=., 4) => { let _: usize = ""; }
|
LL | (1, .=., 4) => { let _: usize = ""; }
|
||||||
| ^ expected pattern
|
| ^ expected pattern
|
||||||
|
|
||||||
error: expected pattern, found `.`
|
error: aborting due to previous error
|
||||||
--> $DIR/recover-tuple-pat.rs:8:10
|
|
||||||
|
|
|
||||||
LL | (.=., 4) => {}
|
|
||||||
| ^ expected pattern
|
|
||||||
|
|
||||||
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";
|
let sl: &[u8] = b"foo";
|
||||||
|
|
||||||
match sl { //~ ERROR non-exhaustive patterns
|
match sl { //~ ERROR non-exhaustive patterns
|
||||||
[first, remainder..] => {},
|
[first, remainder @ ..] => {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ fn slice_pat() {
|
|||||||
let sl: &[u8] = b"foo";
|
let sl: &[u8] = b"foo";
|
||||||
|
|
||||||
match sl {
|
match sl {
|
||||||
[first, remainder..] => {
|
[first, remainder @ ..] => {
|
||||||
let _: &u8 = first;
|
let _: &u8 = first;
|
||||||
assert_eq!(first, &b'f');
|
assert_eq!(first, &b'f');
|
||||||
assert_eq!(remainder, b"oo");
|
assert_eq!(remainder, b"oo");
|
||||||
|
@ -25,7 +25,7 @@ pub fn main() {
|
|||||||
let (_, _,) = (1, 1,);
|
let (_, _,) = (1, 1,);
|
||||||
let [_, _,] = [1, 1,];
|
let [_, _,] = [1, 1,];
|
||||||
let [_, _, .., _,] = [1, 1, 1, 1,];
|
let [_, _, .., _,] = [1, 1, 1, 1,];
|
||||||
let [_, _, _.., _,] = [1, 1, 1, 1,];
|
let [_, _, _, ..,] = [1, 1, 1, 1,];
|
||||||
|
|
||||||
let x: Foo<isize,> = Foo::<isize,>(1);
|
let x: Foo<isize,> = Foo::<isize,>(1);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user