Skip to content

Commit c8fd654

Browse files
authored
Rollup merge of #105502 - chenyukang:yukang/fix-105366-impl, r=estebank
Suggest impl in the scenario of typo with fn Fixes #105366
2 parents 49b9907 + b70a869 commit c8fd654

File tree

6 files changed

+66
-2
lines changed

6 files changed

+66
-2
lines changed

compiler/rustc_error_messages/locales/en-US/parse.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,6 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
362362
363363
parse_invalid_identifier_with_leading_number = expected identifier, found number literal
364364
.label = identifiers cannot start with a number
365+
366+
parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
367+
.suggestion = replace `fn` with `impl` here

compiler/rustc_parse/src/errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1221,3 +1221,11 @@ pub(crate) struct UnexpectedIfWithIf(
12211221
#[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")]
12221222
pub Span,
12231223
);
1224+
1225+
#[derive(Diagnostic)]
1226+
#[diag(parse_maybe_fn_typo_with_impl)]
1227+
pub(crate) struct FnTypoWithImpl {
1228+
#[primary_span]
1229+
#[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")]
1230+
pub fn_span: Span,
1231+
}

compiler/rustc_parse/src/parser/item.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::errors::{DocCommentDoesNotDocumentAnything, UseEmptyBlockNotSemi};
33
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
44
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
55
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
6+
use crate::errors::FnTypoWithImpl;
67
use rustc_ast::ast::*;
78
use rustc_ast::ptr::P;
89
use rustc_ast::token::{self, Delimiter, TokenKind};
@@ -2131,11 +2132,26 @@ impl<'a> Parser<'a> {
21312132
vis: &Visibility,
21322133
case: Case,
21332134
) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
2135+
let fn_span = self.token.span;
21342136
let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
21352137
let ident = self.parse_ident()?; // `foo`
21362138
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
2137-
let decl =
2138-
self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)`
2139+
let decl = match self.parse_fn_decl(
2140+
fn_parse_mode.req_name,
2141+
AllowPlus::Yes,
2142+
RecoverReturnSign::Yes,
2143+
) {
2144+
Ok(decl) => decl,
2145+
Err(old_err) => {
2146+
// If we see `for Ty ...` then user probably meant `impl` item.
2147+
if self.token.is_keyword(kw::For) {
2148+
old_err.cancel();
2149+
return Err(self.sess.create_err(FnTypoWithImpl { fn_span }));
2150+
} else {
2151+
return Err(old_err);
2152+
}
2153+
}
2154+
};
21392155
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
21402156

21412157
let mut sig_hi = self.prev_token.span;

src/test/ui/parser/issue-105366.fixed

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// run-rustfix
2+
3+
struct Foo;
4+
5+
impl From<i32> for Foo {
6+
//~^ ERROR you might have meant to write `impl` instead of `fn`
7+
fn from(_a: i32) -> Self {
8+
Foo
9+
}
10+
}
11+
12+
fn main() {}

src/test/ui/parser/issue-105366.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// run-rustfix
2+
3+
struct Foo;
4+
5+
fn From<i32> for Foo {
6+
//~^ ERROR you might have meant to write `impl` instead of `fn`
7+
fn from(_a: i32) -> Self {
8+
Foo
9+
}
10+
}
11+
12+
fn main() {}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: you might have meant to write `impl` instead of `fn`
2+
--> $DIR/issue-105366.rs:5:1
3+
|
4+
LL | fn From<i32> for Foo {
5+
| ^^
6+
|
7+
help: replace `fn` with `impl` here
8+
|
9+
LL | impl From<i32> for Foo {
10+
| ~~~~
11+
12+
error: aborting due to previous error
13+

0 commit comments

Comments
 (0)