Skip to content

Commit 88a41d6

Browse files
committed
Try to recover from path sep error in parser
1 parent ffa9afe commit 88a41d6

10 files changed

+95
-45
lines changed

Diff for: 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 =

Diff for: compiler/rustc_parse/src/errors.rs

-8
Original file line numberDiff line numberDiff line change
@@ -3071,14 +3071,6 @@ pub(crate) struct BadItemKind {
30713071
pub help: bool,
30723072
}
30733073

3074-
#[derive(Diagnostic)]
3075-
#[diag(parse_single_colon_struct_type)]
3076-
pub(crate) struct SingleColonStructType {
3077-
#[primary_span]
3078-
#[suggestion(code = "::", applicability = "maybe-incorrect", style = "verbose")]
3079-
pub span: Span,
3080-
}
3081-
30823074
#[derive(Diagnostic)]
30833075
#[diag(parse_macro_rules_missing_bang)]
30843076
pub(crate) struct MacroRulesMissingBang {

Diff for: 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()?;

Diff for: compiler/rustc_parse/src/parser/path.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,19 @@ impl<'a> Parser<'a> {
246246
segments.push(segment);
247247

248248
if self.is_import_coupler() || !self.eat_path_sep() {
249-
if style == PathStyle::Expr
250-
&& self.may_recover()
249+
let ok_for_recovery = self.may_recover()
250+
&& match style {
251+
PathStyle::Expr => true,
252+
PathStyle::Type if let Some((ident, _)) = self.prev_token.ident() => {
253+
self.token == token::Colon
254+
&& ident.as_str().chars().all(|c| c.is_lowercase())
255+
&& self.token.span.lo() == self.prev_token.span.hi()
256+
&& self
257+
.look_ahead(1, |token| self.token.span.hi() == token.span.lo())
258+
}
259+
_ => false,
260+
};
261+
if ok_for_recovery
251262
&& self.token == token::Colon
252263
&& self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
253264
{
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+

Diff for: 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,42 +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
8-
|
9-
LL - a: foo:A,
10-
LL + a: foo::A,
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
119
|
10+
LL | a: foo::A,
11+
| +
1212

13-
error: expected `,`, or `}`, found `:`
14-
--> $DIR/struct-field-type-including-single-colon.rs:9:11
15-
|
16-
LL | struct Foo {
17-
| --- while parsing this struct
18-
LL | a: foo:A,
19-
| ^
20-
21-
error: found single colon in a struct field type path
13+
error: path separator must be a double colon
2214
--> $DIR/struct-field-type-including-single-colon.rs:15:16
2315
|
2416
LL | b: foo::bar:B,
2517
| ^
2618
|
27-
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
21+
|
22+
LL | b: foo::bar::B,
23+
| +
24+
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
2830
|
29-
LL - b: foo::bar:B,
30-
LL + b: foo::bar::B,
31+
note: the struct `A` is defined here
32+
--> $DIR/struct-field-type-including-single-colon.rs:2:5
3133
|
34+
LL | struct A;
35+
| ^^^^^^^^^
3236

33-
error: expected `,`, or `}`, found `:`
34-
--> $DIR/struct-field-type-including-single-colon.rs:15:16
37+
error[E0603]: module `bar` is private
38+
--> $DIR/struct-field-type-including-single-colon.rs:15:13
3539
|
36-
LL | struct Bar {
37-
| --- while parsing this struct
3840
LL | b: foo::bar:B,
39-
| ^
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+
| ^^^^^^^
4050

4151
error: aborting due to 4 previous errors
4252

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

0 commit comments

Comments
 (0)