Skip to content

Commit 1e8d1e8

Browse files
bors[bot]adamrk
andauthored
Merge #10689
10689: Handle pub tuple fields in tuple structs r=Veykril a=adamrk The current implementation will throw a parser error for tuple structs that contain a pub tuple field. For example, ```rust struct Foo(pub (u32, u32)); ``` is valid Rust, but rust-analyzer will throw a parser error. This is because the parens after `pub` is treated as a visibility context. Allowing a tuple type to follow `pub` in the special case when we are defining fields in a tuple struct can fix the issue. I guess this is a really minor case because there's not much reason for having a tuple type within a struct tuple, but it is valid rust syntax... Co-authored-by: Adam Bratschi-Kaye <[email protected]>
2 parents e7244e8 + 0d54754 commit 1e8d1e8

File tree

5 files changed

+47
-8
lines changed

5 files changed

+47
-8
lines changed

crates/parser/src/grammar.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ pub(crate) mod entry_points {
7575
}
7676

7777
pub(crate) fn visibility(p: &mut Parser) {
78-
let _ = opt_visibility(p);
78+
let _ = opt_visibility(p, false);
7979
}
8080

8181
// Parse a meta item , which excluded [], e.g : #[ MetaItem ]
@@ -149,7 +149,7 @@ impl BlockLike {
149149
}
150150
}
151151

152-
fn opt_visibility(p: &mut Parser) -> bool {
152+
fn opt_visibility(p: &mut Parser, in_tuple_field: bool) -> bool {
153153
match p.current() {
154154
T![pub] => {
155155
let m = p.start();
@@ -165,9 +165,17 @@ fn opt_visibility(p: &mut Parser) -> bool {
165165
// struct B(pub (super::A));
166166
// struct B(pub (crate::A,));
167167
T![crate] | T![self] | T![super] | T![ident] if p.nth(2) != T![:] => {
168-
p.bump(T!['(']);
169-
paths::use_path(p);
170-
p.expect(T![')']);
168+
// If we are in a tuple struct, then the parens following `pub`
169+
// might be an tuple field, not part of the visibility. So in that
170+
// case we don't want to consume an identifier.
171+
172+
// test pub_tuple_field
173+
// struct MyStruct(pub (u32, u32));
174+
if !(in_tuple_field && matches!(p.nth(1), T![ident])) {
175+
p.bump(T!['(']);
176+
paths::use_path(p);
177+
p.expect(T![')']);
178+
}
171179
}
172180
// test crate_visibility_in
173181
// pub(in super::A) struct S;

crates/parser/src/grammar/items.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool) {
8787
pub(super) fn opt_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
8888
// test_err pub_expr
8989
// fn foo() { pub 92; }
90-
let has_visibility = opt_visibility(p);
90+
let has_visibility = opt_visibility(p, false);
9191

9292
let m = match opt_item_without_modifiers(p, m) {
9393
Ok(()) => return Ok(()),

crates/parser/src/grammar/items/adt.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ pub(crate) fn record_field_list(p: &mut Parser) {
128128
// test record_field_attrs
129129
// struct S { #[attr] f: f32 }
130130
attributes::outer_attrs(p);
131-
opt_visibility(p);
131+
opt_visibility(p, false);
132132
if p.at(IDENT) {
133133
name(p);
134134
p.expect(T![:]);
@@ -150,7 +150,7 @@ fn tuple_field_list(p: &mut Parser) {
150150
// test tuple_field_attrs
151151
// struct S (#[attr] f32);
152152
attributes::outer_attrs(p);
153-
opt_visibility(p);
153+
opt_visibility(p, true);
154154
if !p.at_ts(types::TYPE_FIRST) {
155155
p.error("expected a type");
156156
m.complete(p, ERROR);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
struct MyStruct(pub (u32, u32));

0 commit comments

Comments
 (0)