Rollup merge of #119342 - sjwang05:issue-112254, r=wesleywiser
Emit suggestion when trying to write exclusive ranges as `..<` Closes #112254
This commit is contained in:
commit
7f19365560
@ -23,7 +23,7 @@ use crate::parser;
|
|||||||
use crate::parser::attr::InnerAttrPolicy;
|
use crate::parser::attr::InnerAttrPolicy;
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
|
use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind};
|
||||||
use rustc_ast::tokenstream::AttrTokenTree;
|
use rustc_ast::tokenstream::AttrTokenTree;
|
||||||
use rustc_ast::util::parser::AssocOp;
|
use rustc_ast::util::parser::AssocOp;
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
@ -448,12 +448,11 @@ impl<'a> Parser<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut expected = edible
|
self.expected_tokens.extend(edible.iter().chain(inedible).cloned().map(TokenType::Token));
|
||||||
|
let mut expected = self
|
||||||
|
.expected_tokens
|
||||||
.iter()
|
.iter()
|
||||||
.chain(inedible)
|
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(TokenType::Token)
|
|
||||||
.chain(self.expected_tokens.iter().cloned())
|
|
||||||
.filter(|token| {
|
.filter(|token| {
|
||||||
// Filter out suggestions that suggest the same token which was found and deemed incorrect.
|
// Filter out suggestions that suggest the same token which was found and deemed incorrect.
|
||||||
fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
|
fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
|
||||||
@ -2927,6 +2926,22 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check for exclusive ranges written as `..<`
|
||||||
|
pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: PErr<'a>) -> PErr<'a> {
|
||||||
|
if maybe_lt == token::Lt
|
||||||
|
&& (self.expected_tokens.contains(&TokenType::Token(token::Gt))
|
||||||
|
|| matches!(self.token.kind, token::Literal(..)))
|
||||||
|
{
|
||||||
|
err.span_suggestion(
|
||||||
|
maybe_lt.span,
|
||||||
|
"remove the `<` to write an exclusive range",
|
||||||
|
"",
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
err
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool {
|
pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool {
|
||||||
(0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
|
(0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
|
||||||
&& self.look_ahead(3, |tok| tok == short_kind)
|
&& self.look_ahead(3, |tok| tok == short_kind)
|
||||||
|
@ -482,7 +482,11 @@ impl<'a> Parser<'a> {
|
|||||||
cur_op_span: Span,
|
cur_op_span: Span,
|
||||||
) -> PResult<'a, P<Expr>> {
|
) -> PResult<'a, P<Expr>> {
|
||||||
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
||||||
Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?)
|
let maybe_lt = self.token.clone();
|
||||||
|
Some(
|
||||||
|
self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)
|
||||||
|
.map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -531,11 +535,13 @@ impl<'a> Parser<'a> {
|
|||||||
let attrs = self.parse_or_use_outer_attributes(attrs)?;
|
let attrs = self.parse_or_use_outer_attributes(attrs)?;
|
||||||
self.collect_tokens_for_expr(attrs, |this, attrs| {
|
self.collect_tokens_for_expr(attrs, |this, attrs| {
|
||||||
let lo = this.token.span;
|
let lo = this.token.span;
|
||||||
|
let maybe_lt = this.look_ahead(1, |t| t.clone());
|
||||||
this.bump();
|
this.bump();
|
||||||
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
|
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
|
||||||
// RHS must be parsed with more associativity than the dots.
|
// RHS must be parsed with more associativity than the dots.
|
||||||
this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
|
this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
|
||||||
.map(|x| (lo.to(x.span), Some(x)))?
|
.map(|x| (lo.to(x.span), Some(x)))
|
||||||
|
.map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
|
||||||
} else {
|
} else {
|
||||||
(lo, None)
|
(lo, None)
|
||||||
};
|
};
|
||||||
|
43
tests/ui/parser/range-exclusive-dotdotlt.rs
Normal file
43
tests/ui/parser/range-exclusive-dotdotlt.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
fn foo() {
|
||||||
|
let _ = 0..<10;
|
||||||
|
//~^ ERROR: expected type, found `10`
|
||||||
|
//~| HELP: remove the `<` to write an exclusive range
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar() {
|
||||||
|
let _ = 0..<foo;
|
||||||
|
//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `;`
|
||||||
|
//~| HELP: remove the `<` to write an exclusive range
|
||||||
|
}
|
||||||
|
|
||||||
|
fn baz() {
|
||||||
|
let _ = <foo>;
|
||||||
|
//~^ ERROR: expected `::`, found `;`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn qux() {
|
||||||
|
let _ = [1, 2, 3][..<1];
|
||||||
|
//~^ ERROR: expected type, found `1`
|
||||||
|
//~| HELP: remove the `<` to write an exclusive range
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quux() {
|
||||||
|
let _ = [1, 2, 3][..<foo];
|
||||||
|
//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `]`
|
||||||
|
//~| HELP: remove the `<` to write an exclusive range
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foobar() {
|
||||||
|
let _ = [1, 2, 3][..<foo>];
|
||||||
|
//~^ ERROR: expected `::`, found `]`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ok1() {
|
||||||
|
let _ = [1, 2, 3][..<usize>::default()];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ok2() {
|
||||||
|
let _ = 0..<i32>::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
46
tests/ui/parser/range-exclusive-dotdotlt.stderr
Normal file
46
tests/ui/parser/range-exclusive-dotdotlt.stderr
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
error: expected type, found `10`
|
||||||
|
--> $DIR/range-exclusive-dotdotlt.rs:2:17
|
||||||
|
|
|
||||||
|
LL | let _ = 0..<10;
|
||||||
|
| -^^ expected type
|
||||||
|
| |
|
||||||
|
| help: remove the `<` to write an exclusive range
|
||||||
|
|
||||||
|
error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `;`
|
||||||
|
--> $DIR/range-exclusive-dotdotlt.rs:8:20
|
||||||
|
|
|
||||||
|
LL | let _ = 0..<foo;
|
||||||
|
| - ^ expected one of 7 possible tokens
|
||||||
|
| |
|
||||||
|
| help: remove the `<` to write an exclusive range
|
||||||
|
|
||||||
|
error: expected `::`, found `;`
|
||||||
|
--> $DIR/range-exclusive-dotdotlt.rs:14:18
|
||||||
|
|
|
||||||
|
LL | let _ = <foo>;
|
||||||
|
| ^ expected `::`
|
||||||
|
|
||||||
|
error: expected type, found `1`
|
||||||
|
--> $DIR/range-exclusive-dotdotlt.rs:19:26
|
||||||
|
|
|
||||||
|
LL | let _ = [1, 2, 3][..<1];
|
||||||
|
| -^ expected type
|
||||||
|
| |
|
||||||
|
| help: remove the `<` to write an exclusive range
|
||||||
|
|
||||||
|
error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `]`
|
||||||
|
--> $DIR/range-exclusive-dotdotlt.rs:25:29
|
||||||
|
|
|
||||||
|
LL | let _ = [1, 2, 3][..<foo];
|
||||||
|
| - ^ expected one of 7 possible tokens
|
||||||
|
| |
|
||||||
|
| help: remove the `<` to write an exclusive range
|
||||||
|
|
||||||
|
error: expected `::`, found `]`
|
||||||
|
--> $DIR/range-exclusive-dotdotlt.rs:31:30
|
||||||
|
|
|
||||||
|
LL | let _ = [1, 2, 3][..<foo>];
|
||||||
|
| ^ expected `::`
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user