Skip to content

Commit

Permalink
Rollup merge of #124200 - scrabsha:sasha/->, r=compiler-errors,fmease
Browse files Browse the repository at this point in the history
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](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7f8b6f4433aa7866124123575456f54e))

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)
  • Loading branch information
matthiaskrgr authored Apr 23, 2024
2 parents e9b0c91 + 98332c1 commit 5800e2a
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 4 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ parse_expected_struct_field = expected one of `,`, `:`, or `{"}"}`, found `{$tok
parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
parse_expr_rarrow_call = `->` used for field access or method call
.suggestion = try using `.` instead
.help = the `.` operator will dereference the value if needed
parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
.label = dash-separated idents are not valid
.suggestion = if the original crate name uses dashes you need to use underscores in the code
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2988,3 +2988,12 @@ pub(crate) struct AsyncImpl {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(parse_expr_rarrow_call)]
#[help]
pub(crate) struct ExprRArrowCall {
#[primary_span]
#[suggestion(style = "short", applicability = "machine-applicable", code = ".")]
pub span: Span,
}
6 changes: 6 additions & 0 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,12 @@ impl<'a> Parser<'a> {
// we are using noexpect here because we don't expect a `.` directly after a `return`
// which could be suggested otherwise
self.eat_noexpect(&token::Dot)
} else if self.token.kind == TokenKind::RArrow && self.may_recover() {
// Recovery for `expr->suffix`.
self.bump();
let span = self.prev_token.span;
self.dcx().emit_err(errors::ExprRArrowCall { span });
true
} else {
self.eat(&token::Dot)
};
Expand Down
33 changes: 33 additions & 0 deletions tests/ui/parser/expr-rarrow-call.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//@ run-rustfix
#![allow(
dead_code,
unused_must_use
)]

struct Named {
foo: usize
}

struct Unnamed(usize);

fn named_struct_field_access(named: &Named) {
named.foo; //~ ERROR `->` used for field access or method call
}

fn unnamed_struct_field_access(unnamed: &Unnamed) {
unnamed.0; //~ ERROR `->` used for field access or method call
}

fn tuple_field_access(t: &(u8, u8)) {
t.0; //~ ERROR `->` used for field access or method call
t.1; //~ ERROR `->` used for field access or method call
}

#[derive(Clone)]
struct Foo;

fn method_call(foo: &Foo) {
foo.clone(); //~ ERROR `->` used for field access or method call
}

fn main() {}
33 changes: 33 additions & 0 deletions tests/ui/parser/expr-rarrow-call.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//@ run-rustfix
#![allow(
dead_code,
unused_must_use
)]

struct Named {
foo: usize
}

struct Unnamed(usize);

fn named_struct_field_access(named: &Named) {
named->foo; //~ ERROR `->` used for field access or method call
}

fn unnamed_struct_field_access(unnamed: &Unnamed) {
unnamed->0; //~ ERROR `->` used for field access or method call
}

fn tuple_field_access(t: &(u8, u8)) {
t->0; //~ ERROR `->` used for field access or method call
t->1; //~ ERROR `->` used for field access or method call
}

#[derive(Clone)]
struct Foo;

fn method_call(foo: &Foo) {
foo->clone(); //~ ERROR `->` used for field access or method call
}

fn main() {}
42 changes: 42 additions & 0 deletions tests/ui/parser/expr-rarrow-call.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
error: `->` used for field access or method call
--> $DIR/expr-rarrow-call.rs:14:10
|
LL | named->foo;
| ^^ help: try using `.` instead
|
= help: the `.` operator will dereference the value if needed

error: `->` used for field access or method call
--> $DIR/expr-rarrow-call.rs:18:12
|
LL | unnamed->0;
| ^^ help: try using `.` instead
|
= help: the `.` operator will dereference the value if needed

error: `->` used for field access or method call
--> $DIR/expr-rarrow-call.rs:22:6
|
LL | t->0;
| ^^ help: try using `.` instead
|
= help: the `.` operator will dereference the value if needed

error: `->` used for field access or method call
--> $DIR/expr-rarrow-call.rs:23:6
|
LL | t->1;
| ^^ help: try using `.` instead
|
= help: the `.` operator will dereference the value if needed

error: `->` used for field access or method call
--> $DIR/expr-rarrow-call.rs:30:8
|
LL | foo->clone();
| ^^ help: try using `.` instead
|
= help: the `.` operator will dereference the value if needed

error: aborting due to 5 previous errors

3 changes: 2 additions & 1 deletion tests/ui/parser/issues/issue-118530-ice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ fn bar() -> String {
[1, 2, 3].iter() //~ ERROR expected `;`, found `#`
#[feature]
attr::fn bar() -> String { //~ ERROR expected identifier, found keyword `fn`
//~^ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `->`
//~^ ERROR expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `{`
//~| ERROR expected `;`, found `bar`
//~| ERROR `->` used for field access or method call
#[attr]
[1, 2, 3].iter().map().collect::<String>()
#[attr]
Expand Down
14 changes: 11 additions & 3 deletions tests/ui/parser/issues/issue-118530-ice.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,19 @@ LL | attr::fn bar() -> String {
| |
| help: add `;` here

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `->`
error: `->` used for field access or method call
--> $DIR/issue-118530-ice.rs:5:20
|
LL | attr::fn bar() -> String {
| ^^ expected one of `.`, `;`, `?`, `}`, or an operator
| ^^ help: try using `.` instead
|
= help: the `.` operator will dereference the value if needed

error: expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `{`
--> $DIR/issue-118530-ice.rs:5:30
|
LL | attr::fn bar() -> String {
| ^ expected one of 7 possible tokens

error: aborting due to 4 previous errors
error: aborting due to 5 previous errors

0 comments on commit 5800e2a

Please sign in to comment.