Skip to content
Permalink
Browse files

Ban `...X` pats, harden tests, and improve diagnostics.

Also fix a bug with the span passed in `mk_range`.
  • Loading branch information
Centril committed Jan 11, 2020
1 parent e621797 commit 883932c6baf7acd28ab712b80ddeda960f6e37da
@@ -1966,7 +1966,7 @@ impl<'a> Parser<'a> {
limits: RangeLimits,
) -> PResult<'a, ExprKind> {
if end.is_none() && limits == RangeLimits::Closed {
self.error_inclusive_range_with_no_end(self.token.span);
self.error_inclusive_range_with_no_end(self.prev_span);
Ok(ExprKind::Err)
} else {
Ok(ExprKind::Range(start, end, limits))
@@ -661,14 +661,34 @@ impl<'a> Parser<'a> {
pub(super) fn error_inclusive_range_with_no_end(&self, span: Span) {
use rustc_error_codes::E0586;
struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end")
.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)")
.span_suggestion_short(
span,
"use `..` instead",
"..".to_string(),
Applicability::MachineApplicable,
)
.note("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)")
.emit();
}

/// Parse a range-to pattern, e.g. `..X` and `..=X` where `X` remains to be parsed.
fn parse_pat_range_to(&mut self, re: Spanned<RangeEnd>) -> PResult<'a, PatKind> {
/// Parse a range-to pattern, `..X` or `..=X` where `X` remains to be parsed.
///
/// The form `...X` is prohibited to reduce confusion with the potential
/// expression syntax `...expr` for splatting in expressions.
fn parse_pat_range_to(&mut self, mut re: Spanned<RangeEnd>) -> PResult<'a, PatKind> {
let end = self.parse_pat_range_end()?;
self.sess.gated_spans.gate(sym::half_open_range_patterns, re.span.to(self.prev_span));
if let RangeEnd::Included(ref mut syn @ RangeSyntax::DotDotDot) = &mut re.node {
*syn = RangeSyntax::DotDotEq;
self.struct_span_err(re.span, "range-to patterns with `...` are not allowed")
.span_suggestion_short(
re.span,
"use `..=` instead",
"..=".to_string(),
Applicability::MachineApplicable,
)
.emit();
}
Ok(PatKind::Range(None, Some(end), re))
}

@@ -1,10 +1,10 @@
error[E0586]: inclusive range with no end
--> $DIR/E0586.rs:3:22
--> $DIR/E0586.rs:3:19
|
LL | let x = &tmp[1..=];
| ^
| ^^^ help: use `..` instead
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error: aborting due to previous error

@@ -8,6 +8,7 @@ fn foo() {
//~^ ERROR half-open range patterns are unstable
if let ...5 = 0 {}
//~^ ERROR half-open range patterns are unstable
//~| ERROR range-to patterns with `...` are not allowed
if let ..5 = 0 {}
//~^ ERROR half-open range patterns are unstable
if let 5.. = 0 {}
@@ -1,18 +1,24 @@
error: range-to patterns with `...` are not allowed
--> $DIR/feature-gate-half-open-range-patterns.rs:9:12
|
LL | if let ...5 = 0 {}
| ^^^ help: use `..=` instead

error[E0586]: inclusive range with no end
--> $DIR/feature-gate-half-open-range-patterns.rs:15:13
--> $DIR/feature-gate-half-open-range-patterns.rs:16:13
|
LL | if let 5..= = 0 {}
| ^^^
| ^^^ help: use `..` instead
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error[E0586]: inclusive range with no end
--> $DIR/feature-gate-half-open-range-patterns.rs:18:13
--> $DIR/feature-gate-half-open-range-patterns.rs:19:13
|
LL | if let 5... = 0 {}
| ^^^
| ^^^ help: use `..` instead
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error[E0658]: half-open range patterns are unstable
--> $DIR/feature-gate-half-open-range-patterns.rs:7:12
@@ -33,7 +39,7 @@ LL | if let ...5 = 0 {}
= help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable

error[E0658]: half-open range patterns are unstable
--> $DIR/feature-gate-half-open-range-patterns.rs:11:12
--> $DIR/feature-gate-half-open-range-patterns.rs:12:12
|
LL | if let ..5 = 0 {}
| ^^^
@@ -42,7 +48,7 @@ LL | if let ..5 = 0 {}
= help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable

error[E0658]: half-open range patterns are unstable
--> $DIR/feature-gate-half-open-range-patterns.rs:13:12
--> $DIR/feature-gate-half-open-range-patterns.rs:14:12
|
LL | if let 5.. = 0 {}
| ^^^
@@ -51,7 +57,7 @@ LL | if let 5.. = 0 {}
= help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable

error[E0658]: half-open range patterns are unstable
--> $DIR/feature-gate-half-open-range-patterns.rs:15:12
--> $DIR/feature-gate-half-open-range-patterns.rs:16:12
|
LL | if let 5..= = 0 {}
| ^^^^
@@ -60,15 +66,15 @@ LL | if let 5..= = 0 {}
= help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable

error[E0658]: half-open range patterns are unstable
--> $DIR/feature-gate-half-open-range-patterns.rs:18:12
--> $DIR/feature-gate-half-open-range-patterns.rs:19:12
|
LL | if let 5... = 0 {}
| ^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/67264
= help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable

error: aborting due to 8 previous errors
error: aborting due to 9 previous errors

Some errors have detailed explanations: E0586, E0658.
For more information about an error, try `rustc --explain E0586`.
@@ -0,0 +1,32 @@
// Test that `...X` range-to patterns are syntactically invalid.
//
// See https://github.com/rust-lang/rust/pull/67258#issuecomment-565656155
// for the reason why. To summarize, we might want to introduce `...expr` as
// an expression form for splatting (or "untupling") in an expression context.
// While there is no syntactic ambiguity with `...X` in a pattern context,
// there's a potential confusion factor here, and we would prefer to keep patterns
// and expressions in-sync. As such, we do not allow `...X` in patterns either.

#![feature(half_open_range_patterns)]

fn main() {}

#[cfg(FALSE)]
fn syntax() {
match scrutinee {
...X => {} //~ ERROR range-to patterns with `...` are not allowed
...0 => {} //~ ERROR range-to patterns with `...` are not allowed
...'a' => {} //~ ERROR range-to patterns with `...` are not allowed
...0.0f32 => {} //~ ERROR range-to patterns with `...` are not allowed
}
}

fn syntax2() {
macro_rules! mac {
($e:expr) => {
let ...$e; //~ ERROR range-to patterns with `...` are not allowed
}
}

mac!(0);
}
@@ -0,0 +1,35 @@
error: range-to patterns with `...` are not allowed
--> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:17:9
|
LL | ...X => {}
| ^^^ help: use `..=` instead

error: range-to patterns with `...` are not allowed
--> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:18:9
|
LL | ...0 => {}
| ^^^ help: use `..=` instead

error: range-to patterns with `...` are not allowed
--> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:19:9
|
LL | ...'a' => {}
| ^^^ help: use `..=` instead

error: range-to patterns with `...` are not allowed
--> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:20:9
|
LL | ...0.0f32 => {}
| ^^^ help: use `..=` instead

error: range-to patterns with `...` are not allowed
--> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:27:17
|
LL | let ...$e;
| ^^^ help: use `..=` instead
...
LL | mac!(0);
| -------- in this macro invocation

error: aborting due to 5 previous errors

@@ -13,3 +13,14 @@ fn foo() {
if let X... = 1 {} //~ ERROR inclusive range with no end
if let X..= = 1 {} //~ ERROR inclusive range with no end
}

fn bar() {
macro_rules! mac {
($e:expr) => {
let $e...; //~ ERROR inclusive range with no end
let $e..=; //~ ERROR inclusive range with no end
}
}

mac!(0);
}
@@ -2,34 +2,56 @@ error[E0586]: inclusive range with no end
--> $DIR/half-open-range-pats-inclusive-no-end.rs:10:13
|
LL | if let 0... = 1 {}
| ^^^
| ^^^ help: use `..` instead
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error[E0586]: inclusive range with no end
--> $DIR/half-open-range-pats-inclusive-no-end.rs:11:13
|
LL | if let 0..= = 1 {}
| ^^^
| ^^^ help: use `..` instead
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error[E0586]: inclusive range with no end
--> $DIR/half-open-range-pats-inclusive-no-end.rs:13:13
|
LL | if let X... = 1 {}
| ^^^
| ^^^ help: use `..` instead
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error[E0586]: inclusive range with no end
--> $DIR/half-open-range-pats-inclusive-no-end.rs:14:13
|
LL | if let X..= = 1 {}
| ^^^
| ^^^ help: use `..` instead
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error: aborting due to 4 previous errors
error[E0586]: inclusive range with no end
--> $DIR/half-open-range-pats-inclusive-no-end.rs:20:19
|
LL | let $e...;
| ^^^ help: use `..` instead
...
LL | mac!(0);
| -------- in this macro invocation
|
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error[E0586]: inclusive range with no end
--> $DIR/half-open-range-pats-inclusive-no-end.rs:21:19
|
LL | let $e..=;
| ^^^ help: use `..` instead
...
LL | mac!(0);
| -------- in this macro invocation
|
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0586`.
@@ -20,5 +20,7 @@ fn syntax() {
&..=0 | _ => {}
//~^ ERROR the range pattern here has ambiguous interpretation
&...0 | _ => {}
//~^ ERROR the range pattern here has ambiguous interpretation
//~| ERROR range-to patterns with `...` are not allowed
}
}
@@ -8,9 +8,9 @@ error[E0586]: inclusive range with no end
--> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:11
|
LL | &0..= | _ => {}
| ^^^
| ^^^ help: use `..` instead
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error: the range pattern here has ambiguous interpretation
--> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:10
@@ -22,9 +22,9 @@ error[E0586]: inclusive range with no end
--> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:13:11
|
LL | &0... | _ => {}
| ^^^
| ^^^ help: use `..` instead
|
= help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)

error: the range pattern here has ambiguous interpretation
--> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:18:10
@@ -38,6 +38,18 @@ error: the range pattern here has ambiguous interpretation
LL | &..=0 | _ => {}
| ^^^^ help: add parentheses to clarify the precedence: `(..=0)`

error: aborting due to 6 previous errors
error: range-to patterns with `...` are not allowed
--> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:22:10
|
LL | &...0 | _ => {}
| ^^^ help: use `..=` instead

error: the range pattern here has ambiguous interpretation
--> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:22:10
|
LL | &...0 | _ => {}
| ^^^^ help: add parentheses to clarify the precedence: `(..=0)`

error: aborting due to 8 previous errors

For more information about this error, try `rustc --explain E0586`.
@@ -11,22 +11,20 @@ fn main() {}
fn syntax() {
match scrutinee {
X.. | 0.. | 'a'.. | 0.0f32.. => {}
..=X | ...X | ..X => {}
..=0 | ...0 | ..0 => {}
..='a' | ...'a' | ..'a' => {}
..=0.0f32 | ...0.0f32 | ..0.0f32 => {}
..=X | ..X => {}
..=0 | ..0 => {}
..='a' | ..'a' => {}
..=0.0f32 | ..0.0f32 => {}
}
}

fn syntax2() {
macro_rules! mac {
($e:expr) => {
let ..$e;
let ...$e;
let ..=$e;
let $e..;
let $e...;
let $e..=;
match 0u8 { ..$e => {}, _ => {} }
match 0u8 { ..=$e => {}, _ => {} }
match 0u8 { $e.. => {}, _ => {} }
}
}

mac!(0);
mac!(42u8);
}

0 comments on commit 883932c

Please sign in to comment.
You can’t perform that action at this time.