Skip to content

Commit 7f19365

Browse files
authored
Rollup merge of #119342 - sjwang05:issue-112254, r=wesleywiser
Emit suggestion when trying to write exclusive ranges as `..<` Closes #112254
2 parents 092ea4b + 6dd0772 commit 7f19365

File tree

4 files changed

+117
-7
lines changed

4 files changed

+117
-7
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::parser;
2323
use crate::parser::attr::InnerAttrPolicy;
2424
use rustc_ast as ast;
2525
use rustc_ast::ptr::P;
26-
use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
26+
use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind};
2727
use rustc_ast::tokenstream::AttrTokenTree;
2828
use rustc_ast::util::parser::AssocOp;
2929
use rustc_ast::{
@@ -448,12 +448,11 @@ impl<'a> Parser<'a> {
448448
})
449449
}
450450

451-
let mut expected = edible
451+
self.expected_tokens.extend(edible.iter().chain(inedible).cloned().map(TokenType::Token));
452+
let mut expected = self
453+
.expected_tokens
452454
.iter()
453-
.chain(inedible)
454455
.cloned()
455-
.map(TokenType::Token)
456-
.chain(self.expected_tokens.iter().cloned())
457456
.filter(|token| {
458457
// Filter out suggestions that suggest the same token which was found and deemed incorrect.
459458
fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
@@ -2927,6 +2926,22 @@ impl<'a> Parser<'a> {
29272926
Ok(())
29282927
}
29292928

2929+
/// Check for exclusive ranges written as `..<`
2930+
pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: PErr<'a>) -> PErr<'a> {
2931+
if maybe_lt == token::Lt
2932+
&& (self.expected_tokens.contains(&TokenType::Token(token::Gt))
2933+
|| matches!(self.token.kind, token::Literal(..)))
2934+
{
2935+
err.span_suggestion(
2936+
maybe_lt.span,
2937+
"remove the `<` to write an exclusive range",
2938+
"",
2939+
Applicability::MachineApplicable,
2940+
);
2941+
}
2942+
err
2943+
}
2944+
29302945
pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool {
29312946
(0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
29322947
&& self.look_ahead(3, |tok| tok == short_kind)

compiler/rustc_parse/src/parser/expr.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,11 @@ impl<'a> Parser<'a> {
482482
cur_op_span: Span,
483483
) -> PResult<'a, P<Expr>> {
484484
let rhs = if self.is_at_start_of_range_notation_rhs() {
485-
Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?)
485+
let maybe_lt = self.token.clone();
486+
Some(
487+
self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)
488+
.map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?,
489+
)
486490
} else {
487491
None
488492
};
@@ -531,11 +535,13 @@ impl<'a> Parser<'a> {
531535
let attrs = self.parse_or_use_outer_attributes(attrs)?;
532536
self.collect_tokens_for_expr(attrs, |this, attrs| {
533537
let lo = this.token.span;
538+
let maybe_lt = this.look_ahead(1, |t| t.clone());
534539
this.bump();
535540
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
536541
// RHS must be parsed with more associativity than the dots.
537542
this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
538-
.map(|x| (lo.to(x.span), Some(x)))?
543+
.map(|x| (lo.to(x.span), Some(x)))
544+
.map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
539545
} else {
540546
(lo, None)
541547
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
fn foo() {
2+
let _ = 0..<10;
3+
//~^ ERROR: expected type, found `10`
4+
//~| HELP: remove the `<` to write an exclusive range
5+
}
6+
7+
fn bar() {
8+
let _ = 0..<foo;
9+
//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `;`
10+
//~| HELP: remove the `<` to write an exclusive range
11+
}
12+
13+
fn baz() {
14+
let _ = <foo>;
15+
//~^ ERROR: expected `::`, found `;`
16+
}
17+
18+
fn qux() {
19+
let _ = [1, 2, 3][..<1];
20+
//~^ ERROR: expected type, found `1`
21+
//~| HELP: remove the `<` to write an exclusive range
22+
}
23+
24+
fn quux() {
25+
let _ = [1, 2, 3][..<foo];
26+
//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `]`
27+
//~| HELP: remove the `<` to write an exclusive range
28+
}
29+
30+
fn foobar() {
31+
let _ = [1, 2, 3][..<foo>];
32+
//~^ ERROR: expected `::`, found `]`
33+
}
34+
35+
fn ok1() {
36+
let _ = [1, 2, 3][..<usize>::default()];
37+
}
38+
39+
fn ok2() {
40+
let _ = 0..<i32>::default();
41+
}
42+
43+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
error: expected type, found `10`
2+
--> $DIR/range-exclusive-dotdotlt.rs:2:17
3+
|
4+
LL | let _ = 0..<10;
5+
| -^^ expected type
6+
| |
7+
| help: remove the `<` to write an exclusive range
8+
9+
error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `;`
10+
--> $DIR/range-exclusive-dotdotlt.rs:8:20
11+
|
12+
LL | let _ = 0..<foo;
13+
| - ^ expected one of 7 possible tokens
14+
| |
15+
| help: remove the `<` to write an exclusive range
16+
17+
error: expected `::`, found `;`
18+
--> $DIR/range-exclusive-dotdotlt.rs:14:18
19+
|
20+
LL | let _ = <foo>;
21+
| ^ expected `::`
22+
23+
error: expected type, found `1`
24+
--> $DIR/range-exclusive-dotdotlt.rs:19:26
25+
|
26+
LL | let _ = [1, 2, 3][..<1];
27+
| -^ expected type
28+
| |
29+
| help: remove the `<` to write an exclusive range
30+
31+
error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `]`
32+
--> $DIR/range-exclusive-dotdotlt.rs:25:29
33+
|
34+
LL | let _ = [1, 2, 3][..<foo];
35+
| - ^ expected one of 7 possible tokens
36+
| |
37+
| help: remove the `<` to write an exclusive range
38+
39+
error: expected `::`, found `]`
40+
--> $DIR/range-exclusive-dotdotlt.rs:31:30
41+
|
42+
LL | let _ = [1, 2, 3][..<foo>];
43+
| ^ expected `::`
44+
45+
error: aborting due to 6 previous errors
46+

0 commit comments

Comments
 (0)