Rollup merge of #111120 - chenyukang:yukang-suggest-let, r=Nilstrieb
Suggest let for possible binding with ty Origin from https://github.com/rust-lang/rust/pull/109128#discussion_r1179866137 r? `@Nilstrieb`
This commit is contained in:
commit
8c51701b8a
compiler
tests/ui
@ -140,7 +140,7 @@ pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
|
||||
/// ```fluent
|
||||
/// parser_expected_identifier = expected identifier
|
||||
///
|
||||
/// parser_expected_identifier-found = expected identifier, found {$found}
|
||||
/// parser_expected_identifier_found = expected identifier, found {$found}
|
||||
///
|
||||
/// parser_raw_identifier = escape `{$ident}` to use it as an identifier
|
||||
/// ```
|
||||
|
@ -343,6 +343,7 @@ parse_expected_identifier = expected identifier
|
||||
parse_sugg_escape_identifier = escape `{$ident_name}` to use it as an identifier
|
||||
|
||||
parse_sugg_remove_comma = remove this comma
|
||||
parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding
|
||||
|
||||
parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}`
|
||||
parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}`
|
||||
|
@ -906,6 +906,18 @@ pub(crate) struct SuggRemoveComma {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
parse_sugg_add_let_for_stmt,
|
||||
style = "verbose",
|
||||
applicability = "maybe-incorrect",
|
||||
code = "let "
|
||||
)]
|
||||
pub(crate) struct SuggAddMissingLetStmt {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum ExpectedIdentifierFound {
|
||||
#[label(parse_expected_identifier_found_reserved_identifier)]
|
||||
|
@ -13,7 +13,7 @@ use crate::errors::{
|
||||
IncorrectUseOfAwait, ParenthesesInForHead, ParenthesesInForHeadSugg,
|
||||
PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst,
|
||||
StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens,
|
||||
StructLiteralNeedingParensSugg, SuggEscapeIdentifier, SuggRemoveComma,
|
||||
StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma,
|
||||
UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
|
||||
UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead,
|
||||
};
|
||||
@ -32,8 +32,8 @@ use rustc_ast::{
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{
|
||||
pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
|
||||
FatalError, Handler, IntoDiagnostic, MultiSpan, PResult,
|
||||
pluralize, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage,
|
||||
ErrorGuaranteed, FatalError, Handler, IntoDiagnostic, MultiSpan, PResult,
|
||||
};
|
||||
use rustc_session::errors::ExprParenthesesNeeded;
|
||||
use rustc_span::source_map::Spanned;
|
||||
@ -1006,6 +1006,31 @@ impl<'a> Parser<'a> {
|
||||
Err(e)
|
||||
}
|
||||
|
||||
/// Suggest add the missing `let` before the identifier in stmt
|
||||
/// `a: Ty = 1` -> `let a: Ty = 1`
|
||||
pub(super) fn suggest_add_missing_let_for_stmt(
|
||||
&mut self,
|
||||
err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>,
|
||||
) {
|
||||
if self.token == token::Colon {
|
||||
let prev_span = self.prev_token.span.shrink_to_lo();
|
||||
let snapshot = self.create_snapshot_for_diagnostic();
|
||||
self.bump();
|
||||
match self.parse_ty() {
|
||||
Ok(_) => {
|
||||
if self.token == token::Eq {
|
||||
let sugg = SuggAddMissingLetStmt { span: prev_span };
|
||||
sugg.add_to_diagnostic(err);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
e.cancel();
|
||||
}
|
||||
}
|
||||
self.restore_snapshot(snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check to see if a pair of chained operators looks like an attempt at chained comparison,
|
||||
/// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or
|
||||
/// parenthesising the leftmost comparison.
|
||||
|
@ -103,7 +103,13 @@ impl<'a> Parser<'a> {
|
||||
ForceCollect::Yes => {
|
||||
self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))?
|
||||
}
|
||||
ForceCollect::No => self.parse_stmt_path_start(lo, attrs)?,
|
||||
ForceCollect::No => match self.parse_stmt_path_start(lo, attrs) {
|
||||
Ok(stmt) => stmt,
|
||||
Err(mut err) => {
|
||||
self.suggest_add_missing_let_for_stmt(&mut err);
|
||||
return Err(err);
|
||||
}
|
||||
},
|
||||
}
|
||||
} else if let Some(item) = self.parse_item_common(
|
||||
attrs.clone(),
|
||||
@ -559,7 +565,6 @@ impl<'a> Parser<'a> {
|
||||
if self.token == token::Colon {
|
||||
// if next token is following a colon, it's likely a path
|
||||
// and we can suggest a path separator
|
||||
let ident_span = self.prev_token.span;
|
||||
self.bump();
|
||||
if self.token.span.lo() == self.prev_token.span.hi() {
|
||||
err.span_suggestion_verbose(
|
||||
@ -569,14 +574,6 @@ impl<'a> Parser<'a> {
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
if self.look_ahead(1, |token| token == &token::Eq) {
|
||||
err.span_suggestion_verbose(
|
||||
ident_span.shrink_to_lo(),
|
||||
"you might have meant to introduce a new binding",
|
||||
"let ",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
if self.sess.unstable_features.is_nightly_build() {
|
||||
// FIXME(Nilstrieb): Remove this again after a few months.
|
||||
err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>");
|
||||
|
11
tests/ui/suggestions/type-ascription-instead-of-let.fixed
Normal file
11
tests/ui/suggestions/type-ascription-instead-of-let.fixed
Normal file
@ -0,0 +1,11 @@
|
||||
// run-rustfix
|
||||
|
||||
fn fun(x: i32) -> i32 { x }
|
||||
|
||||
fn main() {
|
||||
let _closure_annotated = |value: i32| -> i32 {
|
||||
let temp: i32 = fun(5i32);
|
||||
//~^ ERROR expected identifier, found `:`
|
||||
temp + value + 1
|
||||
};
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
// run-rustfix
|
||||
|
||||
fn fun(x: i32) -> i32 { x }
|
||||
|
||||
fn main() {
|
||||
let closure_annotated = |value: i32| -> i32 {
|
||||
let _closure_annotated = |value: i32| -> i32 {
|
||||
temp: i32 = fun(5i32);
|
||||
//~^ ERROR expected identifier, found `:`
|
||||
temp + value + 1
|
||||
|
@ -1,8 +1,13 @@
|
||||
error: expected identifier, found `:`
|
||||
--> $DIR/type-ascription-instead-of-let.rs:5:13
|
||||
--> $DIR/type-ascription-instead-of-let.rs:7:13
|
||||
|
|
||||
LL | temp: i32 = fun(5i32);
|
||||
| ^ expected identifier
|
||||
|
|
||||
help: you might have meant to introduce a new binding
|
||||
|
|
||||
LL | let temp: i32 = fun(5i32);
|
||||
| +++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
5
tests/ui/type/missing-let-in-binding-2.fixed
Normal file
5
tests/ui/type/missing-let-in-binding-2.fixed
Normal file
@ -0,0 +1,5 @@
|
||||
// run-rustfix
|
||||
|
||||
fn main() {
|
||||
let _v: Vec<i32> = vec![1, 2, 3]; //~ ERROR expected identifier, found `:`
|
||||
}
|
5
tests/ui/type/missing-let-in-binding-2.rs
Normal file
5
tests/ui/type/missing-let-in-binding-2.rs
Normal file
@ -0,0 +1,5 @@
|
||||
// run-rustfix
|
||||
|
||||
fn main() {
|
||||
_v: Vec<i32> = vec![1, 2, 3]; //~ ERROR expected identifier, found `:`
|
||||
}
|
13
tests/ui/type/missing-let-in-binding-2.stderr
Normal file
13
tests/ui/type/missing-let-in-binding-2.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
error: expected identifier, found `:`
|
||||
--> $DIR/missing-let-in-binding-2.rs:4:7
|
||||
|
|
||||
LL | _v: Vec<i32> = vec![1, 2, 3];
|
||||
| ^ expected identifier
|
||||
|
|
||||
help: you might have meant to introduce a new binding
|
||||
|
|
||||
LL | let _v: Vec<i32> = vec![1, 2, 3];
|
||||
| +++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
5
tests/ui/type/missing-let-in-binding-3.rs
Normal file
5
tests/ui/type/missing-let-in-binding-3.rs
Normal file
@ -0,0 +1,5 @@
|
||||
struct A {
|
||||
: :u8, //~ ERROR expected identifier, found `:`
|
||||
}
|
||||
|
||||
fn main() {}
|
10
tests/ui/type/missing-let-in-binding-3.stderr
Normal file
10
tests/ui/type/missing-let-in-binding-3.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: expected identifier, found `:`
|
||||
--> $DIR/missing-let-in-binding-3.rs:2:5
|
||||
|
|
||||
LL | struct A {
|
||||
| - while parsing this struct
|
||||
LL | : :u8,
|
||||
| ^ expected identifier
|
||||
|
||||
error: aborting due to previous error
|
||||
|
5
tests/ui/type/missing-let-in-binding-4.rs
Normal file
5
tests/ui/type/missing-let-in-binding-4.rs
Normal file
@ -0,0 +1,5 @@
|
||||
struct A {
|
||||
: u8 =, //~ ERROR expected identifier, found `:`
|
||||
}
|
||||
|
||||
fn main() {}
|
10
tests/ui/type/missing-let-in-binding-4.stderr
Normal file
10
tests/ui/type/missing-let-in-binding-4.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: expected identifier, found `:`
|
||||
--> $DIR/missing-let-in-binding-4.rs:2:5
|
||||
|
|
||||
LL | struct A {
|
||||
| - while parsing this struct
|
||||
LL | : u8 =,
|
||||
| ^ expected identifier
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
x
Reference in New Issue
Block a user