Skip to content

Commit 98332c1

Browse files
committed
Improve handling of expr->field errors
The current message for "`->` used for field access" is the following: ```rust error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `->` --> src/main.rs:2:6 | 2 | a->b; | ^^ expected one of 8 possible tokens ``` (playground link[1]) This PR tries to address this by adding a dedicated error message and recovery. The proposed error message is: ``` error: `->` used for field access or method call --> ./tiny_test.rs:2:6 | 2 | a->b; | ^^ help: try using `.` instead | = help: the `.` operator will dereference the value if needed ``` (feel free to bikeshed it as much as necessary) [1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7f8b6f4433aa7866124123575456f54e Signed-off-by: Sasha Pourcelot <sasha.pourcelot@protonmail.com>
1 parent a61b14d commit 98332c1

File tree

8 files changed

+140
-4
lines changed

8 files changed

+140
-4
lines changed

compiler/rustc_parse/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ parse_expected_struct_field = expected one of `,`, `:`, or `{"}"}`, found `{$tok
230230
231231
parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
232232
233+
parse_expr_rarrow_call = `->` used for field access or method call
234+
.suggestion = try using `.` instead
235+
.help = the `.` operator will dereference the value if needed
236+
233237
parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
234238
.label = dash-separated idents are not valid
235239
.suggestion = if the original crate name uses dashes you need to use underscores in the code

compiler/rustc_parse/src/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2988,3 +2988,12 @@ pub(crate) struct AsyncImpl {
29882988
#[primary_span]
29892989
pub span: Span,
29902990
}
2991+
2992+
#[derive(Diagnostic)]
2993+
#[diag(parse_expr_rarrow_call)]
2994+
#[help]
2995+
pub(crate) struct ExprRArrowCall {
2996+
#[primary_span]
2997+
#[suggestion(style = "short", applicability = "machine-applicable", code = ".")]
2998+
pub span: Span,
2999+
}

compiler/rustc_parse/src/parser/expr.rs

+6
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,12 @@ impl<'a> Parser<'a> {
979979
// we are using noexpect here because we don't expect a `.` directly after a `return`
980980
// which could be suggested otherwise
981981
self.eat_noexpect(&token::Dot)
982+
} else if self.token.kind == TokenKind::RArrow && self.may_recover() {
983+
// Recovery for `expr->suffix`.
984+
self.bump();
985+
let span = self.prev_token.span;
986+
self.dcx().emit_err(errors::ExprRArrowCall { span });
987+
true
982988
} else {
983989
self.eat(&token::Dot)
984990
};
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ run-rustfix
2+
#![allow(
3+
dead_code,
4+
unused_must_use
5+
)]
6+
7+
struct Named {
8+
foo: usize
9+
}
10+
11+
struct Unnamed(usize);
12+
13+
fn named_struct_field_access(named: &Named) {
14+
named.foo; //~ ERROR `->` used for field access or method call
15+
}
16+
17+
fn unnamed_struct_field_access(unnamed: &Unnamed) {
18+
unnamed.0; //~ ERROR `->` used for field access or method call
19+
}
20+
21+
fn tuple_field_access(t: &(u8, u8)) {
22+
t.0; //~ ERROR `->` used for field access or method call
23+
t.1; //~ ERROR `->` used for field access or method call
24+
}
25+
26+
#[derive(Clone)]
27+
struct Foo;
28+
29+
fn method_call(foo: &Foo) {
30+
foo.clone(); //~ ERROR `->` used for field access or method call
31+
}
32+
33+
fn main() {}

tests/ui/parser/expr-rarrow-call.rs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ run-rustfix
2+
#![allow(
3+
dead_code,
4+
unused_must_use
5+
)]
6+
7+
struct Named {
8+
foo: usize
9+
}
10+
11+
struct Unnamed(usize);
12+
13+
fn named_struct_field_access(named: &Named) {
14+
named->foo; //~ ERROR `->` used for field access or method call
15+
}
16+
17+
fn unnamed_struct_field_access(unnamed: &Unnamed) {
18+
unnamed->0; //~ ERROR `->` used for field access or method call
19+
}
20+
21+
fn tuple_field_access(t: &(u8, u8)) {
22+
t->0; //~ ERROR `->` used for field access or method call
23+
t->1; //~ ERROR `->` used for field access or method call
24+
}
25+
26+
#[derive(Clone)]
27+
struct Foo;
28+
29+
fn method_call(foo: &Foo) {
30+
foo->clone(); //~ ERROR `->` used for field access or method call
31+
}
32+
33+
fn main() {}
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
error: `->` used for field access or method call
2+
--> $DIR/expr-rarrow-call.rs:14:10
3+
|
4+
LL | named->foo;
5+
| ^^ help: try using `.` instead
6+
|
7+
= help: the `.` operator will dereference the value if needed
8+
9+
error: `->` used for field access or method call
10+
--> $DIR/expr-rarrow-call.rs:18:12
11+
|
12+
LL | unnamed->0;
13+
| ^^ help: try using `.` instead
14+
|
15+
= help: the `.` operator will dereference the value if needed
16+
17+
error: `->` used for field access or method call
18+
--> $DIR/expr-rarrow-call.rs:22:6
19+
|
20+
LL | t->0;
21+
| ^^ help: try using `.` instead
22+
|
23+
= help: the `.` operator will dereference the value if needed
24+
25+
error: `->` used for field access or method call
26+
--> $DIR/expr-rarrow-call.rs:23:6
27+
|
28+
LL | t->1;
29+
| ^^ help: try using `.` instead
30+
|
31+
= help: the `.` operator will dereference the value if needed
32+
33+
error: `->` used for field access or method call
34+
--> $DIR/expr-rarrow-call.rs:30:8
35+
|
36+
LL | foo->clone();
37+
| ^^ help: try using `.` instead
38+
|
39+
= help: the `.` operator will dereference the value if needed
40+
41+
error: aborting due to 5 previous errors
42+

tests/ui/parser/issues/issue-118530-ice.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ fn bar() -> String {
33
[1, 2, 3].iter() //~ ERROR expected `;`, found `#`
44
#[feature]
55
attr::fn bar() -> String { //~ ERROR expected identifier, found keyword `fn`
6-
//~^ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `->`
6+
//~^ ERROR expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `{`
77
//~| ERROR expected `;`, found `bar`
8+
//~| ERROR `->` used for field access or method call
89
#[attr]
910
[1, 2, 3].iter().map().collect::<String>()
1011
#[attr]

tests/ui/parser/issues/issue-118530-ice.stderr

+11-3
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,19 @@ LL | attr::fn bar() -> String {
3333
| |
3434
| help: add `;` here
3535

36-
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `->`
36+
error: `->` used for field access or method call
3737
--> $DIR/issue-118530-ice.rs:5:20
3838
|
3939
LL | attr::fn bar() -> String {
40-
| ^^ expected one of `.`, `;`, `?`, `}`, or an operator
40+
| ^^ help: try using `.` instead
41+
|
42+
= help: the `.` operator will dereference the value if needed
43+
44+
error: expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `{`
45+
--> $DIR/issue-118530-ice.rs:5:30
46+
|
47+
LL | attr::fn bar() -> String {
48+
| ^ expected one of 7 possible tokens
4149

42-
error: aborting due to 4 previous errors
50+
error: aborting due to 5 previous errors
4351

0 commit comments

Comments
 (0)