fix #105366, suggest impl in the scenario of typo with fn
This commit is contained in:
parent
7701a7e7d4
commit
b70a869d8f
6 changed files with 66 additions and 2 deletions
|
@ -362,3 +362,6 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
|
||||||
|
|
||||||
parse_invalid_identifier_with_leading_number = expected identifier, found number literal
|
parse_invalid_identifier_with_leading_number = expected identifier, found number literal
|
||||||
.label = identifiers cannot start with a number
|
.label = identifiers cannot start with a number
|
||||||
|
|
||||||
|
parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
|
||||||
|
.suggestion = replace `fn` with `impl` here
|
||||||
|
|
|
@ -1221,3 +1221,11 @@ pub(crate) struct UnexpectedIfWithIf(
|
||||||
#[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")]
|
#[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")]
|
||||||
pub Span,
|
pub Span,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parse_maybe_fn_typo_with_impl)]
|
||||||
|
pub(crate) struct FnTypoWithImpl {
|
||||||
|
#[primary_span]
|
||||||
|
#[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")]
|
||||||
|
pub fn_span: Span,
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::errors::{DocCommentDoesNotDocumentAnything, UseEmptyBlockNotSemi};
|
||||||
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
|
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
|
||||||
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
||||||
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
|
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
|
||||||
|
use crate::errors::FnTypoWithImpl;
|
||||||
use rustc_ast::ast::*;
|
use rustc_ast::ast::*;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Delimiter, TokenKind};
|
use rustc_ast::token::{self, Delimiter, TokenKind};
|
||||||
|
@ -2126,11 +2127,26 @@ impl<'a> Parser<'a> {
|
||||||
vis: &Visibility,
|
vis: &Visibility,
|
||||||
case: Case,
|
case: Case,
|
||||||
) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
|
) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
|
||||||
|
let fn_span = self.token.span;
|
||||||
let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
|
let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
|
||||||
let ident = self.parse_ident()?; // `foo`
|
let ident = self.parse_ident()?; // `foo`
|
||||||
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
|
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
|
||||||
let decl =
|
let decl = match self.parse_fn_decl(
|
||||||
self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)`
|
fn_parse_mode.req_name,
|
||||||
|
AllowPlus::Yes,
|
||||||
|
RecoverReturnSign::Yes,
|
||||||
|
) {
|
||||||
|
Ok(decl) => decl,
|
||||||
|
Err(old_err) => {
|
||||||
|
// If we see `for Ty ...` then user probably meant `impl` item.
|
||||||
|
if self.token.is_keyword(kw::For) {
|
||||||
|
old_err.cancel();
|
||||||
|
return Err(self.sess.create_err(FnTypoWithImpl { fn_span }));
|
||||||
|
} else {
|
||||||
|
return Err(old_err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
|
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
|
||||||
|
|
||||||
let mut sig_hi = self.prev_token.span;
|
let mut sig_hi = self.prev_token.span;
|
||||||
|
|
12
src/test/ui/parser/issue-105366.fixed
Normal file
12
src/test/ui/parser/issue-105366.fixed
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl From<i32> for Foo {
|
||||||
|
//~^ ERROR you might have meant to write `impl` instead of `fn`
|
||||||
|
fn from(_a: i32) -> Self {
|
||||||
|
Foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
12
src/test/ui/parser/issue-105366.rs
Normal file
12
src/test/ui/parser/issue-105366.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
fn From<i32> for Foo {
|
||||||
|
//~^ ERROR you might have meant to write `impl` instead of `fn`
|
||||||
|
fn from(_a: i32) -> Self {
|
||||||
|
Foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
13
src/test/ui/parser/issue-105366.stderr
Normal file
13
src/test/ui/parser/issue-105366.stderr
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
error: you might have meant to write `impl` instead of `fn`
|
||||||
|
--> $DIR/issue-105366.rs:5:1
|
||||||
|
|
|
||||||
|
LL | fn From<i32> for Foo {
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
help: replace `fn` with `impl` here
|
||||||
|
|
|
||||||
|
LL | impl From<i32> for Foo {
|
||||||
|
| ~~~~
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue