Skip to content

Commit 949333b

Browse files
committed
Try to recover from path sep error in parser
1 parent 43ca9d1 commit 949333b

10 files changed

+99
-42
lines changed

compiler/rustc_parse/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -743,9 +743,6 @@ parse_single_colon_import_path = expected `::`, found `:`
743743
.suggestion = use double colon
744744
.note = import paths are delimited using `::`
745745
746-
parse_single_colon_struct_type = found single colon in a struct field type path
747-
.suggestion = write a path separator here
748-
749746
parse_static_with_generics = static items may not have generic parameters
750747
751748
parse_struct_literal_body_without_path =

compiler/rustc_parse/src/errors.rs

-8
Original file line numberDiff line numberDiff line change
@@ -3059,14 +3059,6 @@ pub(crate) struct BadItemKind {
30593059
pub help: bool,
30603060
}
30613061

3062-
#[derive(Diagnostic)]
3063-
#[diag(parse_single_colon_struct_type)]
3064-
pub(crate) struct SingleColonStructType {
3065-
#[primary_span]
3066-
#[suggestion(code = "::", applicability = "maybe-incorrect", style = "verbose")]
3067-
pub span: Span,
3068-
}
3069-
30703062
#[derive(Diagnostic)]
30713063
#[diag(parse_macro_rules_missing_bang)]
30723064
pub(crate) struct MacroRulesMissingBang {

compiler/rustc_parse/src/parser/item.rs

-3
Original file line numberDiff line numberDiff line change
@@ -2043,9 +2043,6 @@ impl<'a> Parser<'a> {
20432043
}
20442044
self.expect_field_ty_separator()?;
20452045
let ty = self.parse_ty()?;
2046-
if self.token == token::Colon && self.look_ahead(1, |t| *t != token::Colon) {
2047-
self.dcx().emit_err(errors::SingleColonStructType { span: self.token.span });
2048-
}
20492046
let default = if self.token == token::Eq {
20502047
self.bump();
20512048
let const_expr = self.parse_expr_anon_const()?;

compiler/rustc_parse/src/parser/path.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,24 @@ impl<'a> Parser<'a> {
247247
segments.push(segment);
248248

249249
if self.is_import_coupler() || !self.eat_path_sep() {
250-
if style == PathStyle::Expr
251-
&& self.may_recover()
250+
let ok_for_recovery = match style {
251+
PathStyle::Expr => self.may_recover(),
252+
PathStyle::Type => {
253+
self.may_recover()
254+
&& if let Some((ident, _)) = self.prev_token.ident() {
255+
ident.as_str().chars().all(|c| c.is_lowercase())
256+
&& self.token == token::Colon
257+
&& self.token.span.lo() == self.prev_token.span.hi()
258+
&& self.look_ahead(1, |token| {
259+
self.token.span.hi() == token.span.lo()
260+
})
261+
} else {
262+
false
263+
}
264+
}
265+
_ => false,
266+
};
267+
if ok_for_recovery
252268
&& self.token == token::Colon
253269
&& self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
254270
{
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
error: path separator must be a double colon
22
--> $DIR/single-colon-path-not-const-generics.rs:8:18
33
|
4-
LL | pub struct Foo {
5-
| --- while parsing this struct
64
LL | a: Vec<foo::bar:A>,
75
| ^
86
|
97
= note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
108
help: use a double colon instead
119
|
1210
LL | a: Vec<foo::bar::A>,
13-
| +
11+
| +
1412

1513
error: aborting due to 1 previous error
1614

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ run-rustfix
2+
3+
use std::fmt;
4+
5+
struct Hello;
6+
7+
impl fmt::Display for Hello {
8+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { //~ ERROR path separator must be a double colon
9+
write!(f, "hello")
10+
}
11+
}
12+
13+
fn main() {
14+
let _ = Hello;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ run-rustfix
2+
3+
use std::fmt;
4+
5+
struct Hello;
6+
7+
impl fmt::Display for Hello {
8+
fn fmt(&self, f: &mut fmt:Formatter) -> fmt::Result { //~ ERROR path separator must be a double colon
9+
write!(f, "hello")
10+
}
11+
}
12+
13+
fn main() {
14+
let _ = Hello;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: path separator must be a double colon
2+
--> $DIR/argument-list-from-path-sep-error-129273.rs:8:30
3+
|
4+
LL | fn fmt(&self, f: &mut fmt:Formatter) -> fmt::Result {
5+
| ^
6+
|
7+
= note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
8+
help: use a double colon instead
9+
|
10+
LL | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11+
| +
12+
13+
error: aborting due to 1 previous error
14+

tests/ui/suggestions/struct-field-type-including-single-colon.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ mod foo {
77

88
struct Foo {
99
a: foo:A,
10-
//~^ ERROR found single colon in a struct field type path
11-
//~| expected `,`, or `}`, found `:`
10+
//~^ ERROR path separator must be a double colon
11+
//~| ERROR struct `A` is private
1212
}
1313

1414
struct Bar {
1515
b: foo::bar:B,
16-
//~^ ERROR found single colon in a struct field type path
17-
//~| expected `,`, or `}`, found `:`
16+
//~^ ERROR path separator must be a double colon
17+
//~| ERROR module `bar` is private
1818
}
1919

2020
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,53 @@
1-
error: found single colon in a struct field type path
1+
error: path separator must be a double colon
22
--> $DIR/struct-field-type-including-single-colon.rs:9:11
33
|
44
LL | a: foo:A,
55
| ^
66
|
7-
help: write a path separator here
7+
= note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
8+
help: use a double colon instead
89
|
910
LL | a: foo::A,
10-
| ~~
11+
| +
1112

12-
error: expected `,`, or `}`, found `:`
13-
--> $DIR/struct-field-type-including-single-colon.rs:9:11
14-
|
15-
LL | struct Foo {
16-
| --- while parsing this struct
17-
LL | a: foo:A,
18-
| ^
19-
20-
error: found single colon in a struct field type path
13+
error: path separator must be a double colon
2114
--> $DIR/struct-field-type-including-single-colon.rs:15:16
2215
|
2316
LL | b: foo::bar:B,
2417
| ^
2518
|
26-
help: write a path separator here
19+
= note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
20+
help: use a double colon instead
2721
|
2822
LL | b: foo::bar::B,
29-
| ~~
23+
| +
3024

31-
error: expected `,`, or `}`, found `:`
32-
--> $DIR/struct-field-type-including-single-colon.rs:15:16
25+
error[E0603]: struct `A` is private
26+
--> $DIR/struct-field-type-including-single-colon.rs:9:12
27+
|
28+
LL | a: foo:A,
29+
| ^ private struct
30+
|
31+
note: the struct `A` is defined here
32+
--> $DIR/struct-field-type-including-single-colon.rs:2:5
33+
|
34+
LL | struct A;
35+
| ^^^^^^^^^
36+
37+
error[E0603]: module `bar` is private
38+
--> $DIR/struct-field-type-including-single-colon.rs:15:13
3339
|
34-
LL | struct Bar {
35-
| --- while parsing this struct
3640
LL | b: foo::bar:B,
37-
| ^
41+
| ^^^ - struct `B` is not publicly re-exported
42+
| |
43+
| private module
44+
|
45+
note: the module `bar` is defined here
46+
--> $DIR/struct-field-type-including-single-colon.rs:3:5
47+
|
48+
LL | mod bar {
49+
| ^^^^^^^
3850

3951
error: aborting due to 4 previous errors
4052

53+
For more information about this error, try `rustc --explain E0603`.

0 commit comments

Comments
 (0)