Recover parentheses in range patterns
Co-authored-by: León Orell Valerian Liehr <me@fmease.dev>
This commit is contained in:
parent
e51e98dde6
commit
4e0baddbbf
@ -767,6 +767,9 @@ parse_unexpected_if_with_if = unexpected `if` in the condition expression
|
|||||||
parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
|
parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
|
||||||
.suggestion = remove the lifetime
|
.suggestion = remove the lifetime
|
||||||
|
|
||||||
|
parse_unexpected_paren_in_range_pat = range pattern bounds cannot have parentheses
|
||||||
|
parse_unexpected_paren_in_range_pat_sugg = remove these parentheses
|
||||||
|
|
||||||
parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head
|
parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head
|
||||||
.suggestion = remove parentheses in `for` loop
|
.suggestion = remove parentheses in `for` loop
|
||||||
|
|
||||||
|
@ -2378,6 +2378,27 @@ pub(crate) struct ExpectedCommaAfterPatternField {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parse_unexpected_paren_in_range_pat)]
|
||||||
|
pub(crate) struct UnexpectedParenInRangePat {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Vec<Span>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sugg: UnexpectedParenInRangePatSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(
|
||||||
|
parse_unexpected_paren_in_range_pat_sugg,
|
||||||
|
applicability = "machine-applicable"
|
||||||
|
)]
|
||||||
|
pub(crate) struct UnexpectedParenInRangePatSugg {
|
||||||
|
#[suggestion_part(code = "")]
|
||||||
|
pub start_span: Span,
|
||||||
|
#[suggestion_part(code = "")]
|
||||||
|
pub end_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(parse_return_types_use_thin_arrow)]
|
#[diag(parse_return_types_use_thin_arrow)]
|
||||||
pub(crate) struct ReturnTypesUseThinArrow {
|
pub(crate) struct ReturnTypesUseThinArrow {
|
||||||
|
@ -6,7 +6,8 @@ use crate::errors::{
|
|||||||
InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
|
InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
|
||||||
PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern,
|
PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern,
|
||||||
SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
|
SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
|
||||||
TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
|
TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat,
|
||||||
|
UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam,
|
||||||
UnexpectedVertVertInPattern,
|
UnexpectedVertVertInPattern,
|
||||||
};
|
};
|
||||||
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
||||||
@ -579,6 +580,8 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
/// Parse a tuple or parenthesis pattern.
|
/// Parse a tuple or parenthesis pattern.
|
||||||
fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
|
fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
|
||||||
|
let open_paren = self.token.span;
|
||||||
|
|
||||||
let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
|
let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
|
||||||
p.parse_pat_allow_top_alt(
|
p.parse_pat_allow_top_alt(
|
||||||
None,
|
None,
|
||||||
@ -591,7 +594,29 @@ impl<'a> Parser<'a> {
|
|||||||
// Here, `(pat,)` is a tuple pattern.
|
// Here, `(pat,)` is a tuple pattern.
|
||||||
// For backward compatibility, `(..)` is a tuple pattern as well.
|
// For backward compatibility, `(..)` is a tuple pattern as well.
|
||||||
Ok(if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) {
|
Ok(if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) {
|
||||||
PatKind::Paren(fields.into_iter().next().unwrap())
|
let pat = fields.into_iter().next().unwrap();
|
||||||
|
let close_paren = self.prev_token.span;
|
||||||
|
|
||||||
|
match &pat.kind {
|
||||||
|
// recover ranges with parentheses around the `(start)..`
|
||||||
|
PatKind::Lit(begin)
|
||||||
|
if self.may_recover()
|
||||||
|
&& let Some(form) = self.parse_range_end() =>
|
||||||
|
{
|
||||||
|
self.dcx().emit_err(UnexpectedParenInRangePat {
|
||||||
|
span: vec![open_paren, close_paren],
|
||||||
|
sugg: UnexpectedParenInRangePatSugg {
|
||||||
|
start_span: open_paren,
|
||||||
|
end_span: close_paren,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
self.parse_pat_range_begin_with(begin.clone(), form)?
|
||||||
|
}
|
||||||
|
|
||||||
|
// (pat) with optional parentheses
|
||||||
|
_ => PatKind::Paren(pat),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
PatKind::Tuple(fields)
|
PatKind::Tuple(fields)
|
||||||
})
|
})
|
||||||
@ -794,11 +819,21 @@ impl<'a> Parser<'a> {
|
|||||||
|| t.can_begin_literal_maybe_minus() // e.g. `42`.
|
|| t.can_begin_literal_maybe_minus() // e.g. `42`.
|
||||||
|| t.is_whole_expr()
|
|| t.is_whole_expr()
|
||||||
|| t.is_lifetime() // recover `'a` instead of `'a'`
|
|| t.is_lifetime() // recover `'a` instead of `'a'`
|
||||||
|
|| (self.may_recover() // recover leading `(`
|
||||||
|
&& t.kind == token::OpenDelim(Delimiter::Parenthesis)
|
||||||
|
&& self.look_ahead(dist + 1, |t| t.kind != token::OpenDelim(Delimiter::Parenthesis))
|
||||||
|
&& self.is_pat_range_end_start(dist + 1))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a range pattern end bound
|
||||||
fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
if self.check_inline_const(0) {
|
// recover leading `(`
|
||||||
|
let open_paren = (self.may_recover()
|
||||||
|
&& self.eat_noexpect(&token::OpenDelim(Delimiter::Parenthesis)))
|
||||||
|
.then_some(self.prev_token.span);
|
||||||
|
|
||||||
|
let bound = if self.check_inline_const(0) {
|
||||||
self.parse_const_block(self.token.span, true)
|
self.parse_const_block(self.token.span, true)
|
||||||
} else if self.check_path() {
|
} else if self.check_path() {
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
@ -814,7 +849,22 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path)))
|
Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path)))
|
||||||
} else {
|
} else {
|
||||||
self.parse_literal_maybe_minus()
|
self.parse_literal_maybe_minus()
|
||||||
|
}?;
|
||||||
|
|
||||||
|
// recover trailing `)`
|
||||||
|
if let Some(open_paren) = open_paren {
|
||||||
|
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
|
||||||
|
|
||||||
|
self.dcx().emit_err(UnexpectedParenInRangePat {
|
||||||
|
span: vec![open_paren, self.prev_token.span],
|
||||||
|
sugg: UnexpectedParenInRangePatSugg {
|
||||||
|
start_span: open_paren,
|
||||||
|
end_span: self.prev_token.span,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(bound)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this the start of a pattern beginning with a path?
|
/// Is this the start of a pattern beginning with a path?
|
||||||
|
@ -8,8 +8,7 @@ fn main() {
|
|||||||
for x in -9 + 1..=(9 - 2) {
|
for x in -9 + 1..=(9 - 2) {
|
||||||
match x as i32 {
|
match x as i32 {
|
||||||
0..=(5+1) => errors_only.push(x),
|
0..=(5+1) => errors_only.push(x),
|
||||||
//~^ error: inclusive range with no end
|
//~^ error: expected `)`, found `+`
|
||||||
//~| error: expected one of `=>`, `if`, or `|`, found `(`
|
|
||||||
1 | -3..0 => first_or.push(x),
|
1 | -3..0 => first_or.push(x),
|
||||||
y @ (0..5 | 6) => or_two.push(y),
|
y @ (0..5 | 6) => or_two.push(y),
|
||||||
y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
|
y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
|
||||||
|
@ -1,17 +1,8 @@
|
|||||||
error[E0586]: inclusive range with no end
|
error: expected `)`, found `+`
|
||||||
--> $DIR/range_pat_interactions2.rs:10:14
|
--> $DIR/range_pat_interactions2.rs:10:19
|
||||||
|
|
|
|
||||||
LL | 0..=(5+1) => errors_only.push(x),
|
LL | 0..=(5+1) => errors_only.push(x),
|
||||||
| ^^^ help: use `..` instead
|
| ^ expected `)`
|
||||||
|
|
|
||||||
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
|
|
||||||
|
|
||||||
error: expected one of `=>`, `if`, or `|`, found `(`
|
error: aborting due to 1 previous error
|
||||||
--> $DIR/range_pat_interactions2.rs:10:17
|
|
||||||
|
|
|
||||||
LL | 0..=(5+1) => errors_only.push(x),
|
|
||||||
| ^ expected one of `=>`, `if`, or `|`
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0586`.
|
|
||||||
|
19
tests/ui/parser/pat-recover-ranges.rs
Normal file
19
tests/ui/parser/pat-recover-ranges.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
fn main() {
|
||||||
|
match -1 {
|
||||||
|
0..=1 => (),
|
||||||
|
0..=(1) => (),
|
||||||
|
//~^ error: range pattern bounds cannot have parentheses
|
||||||
|
(-12)..=4 => (),
|
||||||
|
//~^ error: range pattern bounds cannot have parentheses
|
||||||
|
(0)..=(-4) => (),
|
||||||
|
//~^ error: range pattern bounds cannot have parentheses
|
||||||
|
//~| error: range pattern bounds cannot have parentheses
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! m {
|
||||||
|
($pat:pat) => {};
|
||||||
|
(($s:literal)..($e:literal)) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
m!((7)..(7));
|
50
tests/ui/parser/pat-recover-ranges.stderr
Normal file
50
tests/ui/parser/pat-recover-ranges.stderr
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
error: range pattern bounds cannot have parentheses
|
||||||
|
--> $DIR/pat-recover-ranges.rs:4:13
|
||||||
|
|
|
||||||
|
LL | 0..=(1) => (),
|
||||||
|
| ^ ^
|
||||||
|
|
|
||||||
|
help: remove these parentheses
|
||||||
|
|
|
||||||
|
LL - 0..=(1) => (),
|
||||||
|
LL + 0..=1 => (),
|
||||||
|
|
|
||||||
|
|
||||||
|
error: range pattern bounds cannot have parentheses
|
||||||
|
--> $DIR/pat-recover-ranges.rs:6:9
|
||||||
|
|
|
||||||
|
LL | (-12)..=4 => (),
|
||||||
|
| ^ ^
|
||||||
|
|
|
||||||
|
help: remove these parentheses
|
||||||
|
|
|
||||||
|
LL - (-12)..=4 => (),
|
||||||
|
LL + -12..=4 => (),
|
||||||
|
|
|
||||||
|
|
||||||
|
error: range pattern bounds cannot have parentheses
|
||||||
|
--> $DIR/pat-recover-ranges.rs:8:9
|
||||||
|
|
|
||||||
|
LL | (0)..=(-4) => (),
|
||||||
|
| ^ ^
|
||||||
|
|
|
||||||
|
help: remove these parentheses
|
||||||
|
|
|
||||||
|
LL - (0)..=(-4) => (),
|
||||||
|
LL + 0..=(-4) => (),
|
||||||
|
|
|
||||||
|
|
||||||
|
error: range pattern bounds cannot have parentheses
|
||||||
|
--> $DIR/pat-recover-ranges.rs:8:15
|
||||||
|
|
|
||||||
|
LL | (0)..=(-4) => (),
|
||||||
|
| ^ ^
|
||||||
|
|
|
||||||
|
help: remove these parentheses
|
||||||
|
|
|
||||||
|
LL - (0)..=(-4) => (),
|
||||||
|
LL + (0)..=-4 => (),
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user