Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,8 @@ impl<'a> Parser<'a> {
let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
let limits =
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits), AttrVec::new()))
let range = self.mk_range(Some(lhs), rhs, limits);
Ok(self.mk_expr(span, range, AttrVec::new()))
}

fn is_at_start_of_range_notation_rhs(&self) -> bool {
Expand Down Expand Up @@ -479,7 +480,8 @@ impl<'a> Parser<'a> {
} else {
(lo, None)
};
Ok(this.mk_expr(span, this.mk_range(None, opt_end, limits), attrs.into()))
let range = this.mk_range(None, opt_end, limits);
Ok(this.mk_expr(span, range, attrs.into()))
})
}

Expand Down Expand Up @@ -2517,13 +2519,13 @@ impl<'a> Parser<'a> {
}

fn mk_range(
&self,
&mut self,
start: Option<P<Expr>>,
end: Option<P<Expr>>,
limits: RangeLimits,
) -> ExprKind {
if end.is_none() && limits == RangeLimits::Closed {
self.error_inclusive_range_with_no_end(self.prev_token.span);
self.inclusive_range_with_incorrect_end(self.prev_token.span);
ExprKind::Err
} else {
ExprKind::Range(start, end, limits)
Expand Down
39 changes: 36 additions & 3 deletions compiler/rustc_parse/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,15 +736,48 @@ impl<'a> Parser<'a> {
// Parsing e.g. `X..`.
if let RangeEnd::Included(_) = re.node {
// FIXME(Centril): Consider semantic errors instead in `ast_validation`.
// Possibly also do this for `X..=` in *expression* contexts.
self.error_inclusive_range_with_no_end(re.span);
self.inclusive_range_with_incorrect_end(re.span);
}
None
};
Ok(PatKind::Range(Some(begin), end, re))
}

pub(super) fn error_inclusive_range_with_no_end(&self, span: Span) {
pub(super) fn inclusive_range_with_incorrect_end(&mut self, span: Span) {
let tok = &self.token;

// If the user typed "..==" instead of "..=", we want to give them
// a specific error message telling them to use "..=".
// Otherwise, we assume that they meant to type a half open exclusive
// range and give them an error telling them to do that instead.
if matches!(tok.kind, token::Eq) && tok.span.lo() == span.hi() {
let span_with_eq = span.to(tok.span);

// Ensure the user doesn't receive unhelpful unexpected token errors
self.bump();
if self.is_pat_range_end_start(0) {
let _ = self.parse_pat_range_end();
}

self.error_inclusive_range_with_extra_equals(span_with_eq);
} else {
self.error_inclusive_range_with_no_end(span);
}
}

fn error_inclusive_range_with_extra_equals(&self, span: Span) {
self.struct_span_err(span, "unexpected `=` after inclusive range")
.span_suggestion_short(
span,
"use `..=` instead",
"..=".to_string(),
Applicability::MaybeIncorrect,
)
.note("inclusive ranges end with a single equals sign (`..=`)")
.emit();
}

fn error_inclusive_range_with_no_end(&self, span: Span) {
struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end")
.span_suggestion_short(
span,
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/parser/range-inclusive-extra-equals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Makes sure that a helpful message is shown when someone mistypes
// an inclusive range as `..==` rather than `..=`. This is an
// easy mistake, because of the resemblance to`==`.
// See #86395 for a bit of background.

pub fn main() {
if let 1..==3 = 1 {} //~ERROR unexpected `=` after inclusive range
//~|HELP use `..=` instead
//~|NOTE inclusive ranges end with a single equals sign
}
10 changes: 10 additions & 0 deletions src/test/ui/parser/range-inclusive-extra-equals.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: unexpected `=` after inclusive range
--> $DIR/range-inclusive-extra-equals.rs:7:13
|
LL | if let 1..==3 = 1 {}
| ^^^^ help: use `..=` instead
|
= note: inclusive ranges end with a single equals sign (`..=`)

error: aborting due to previous error