mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
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 <ark.email@gmail.com>
This commit is contained in:
commit
1e8d1e84b2
5 changed files with 47 additions and 8 deletions
|
@ -75,7 +75,7 @@ pub(crate) mod entry_points {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn visibility(p: &mut Parser) {
|
pub(crate) fn visibility(p: &mut Parser) {
|
||||||
let _ = opt_visibility(p);
|
let _ = opt_visibility(p, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse a meta item , which excluded [], e.g : #[ MetaItem ]
|
// Parse a meta item , which excluded [], e.g : #[ MetaItem ]
|
||||||
|
@ -149,7 +149,7 @@ impl BlockLike {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opt_visibility(p: &mut Parser) -> bool {
|
fn opt_visibility(p: &mut Parser, in_tuple_field: bool) -> bool {
|
||||||
match p.current() {
|
match p.current() {
|
||||||
T![pub] => {
|
T![pub] => {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
|
@ -165,9 +165,17 @@ fn opt_visibility(p: &mut Parser) -> bool {
|
||||||
// struct B(pub (super::A));
|
// struct B(pub (super::A));
|
||||||
// struct B(pub (crate::A,));
|
// struct B(pub (crate::A,));
|
||||||
T![crate] | T![self] | T![super] | T![ident] if p.nth(2) != T![:] => {
|
T![crate] | T![self] | T![super] | T![ident] if p.nth(2) != T![:] => {
|
||||||
p.bump(T!['(']);
|
// If we are in a tuple struct, then the parens following `pub`
|
||||||
paths::use_path(p);
|
// might be an tuple field, not part of the visibility. So in that
|
||||||
p.expect(T![')']);
|
// case we don't want to consume an identifier.
|
||||||
|
|
||||||
|
// test pub_tuple_field
|
||||||
|
// struct MyStruct(pub (u32, u32));
|
||||||
|
if !(in_tuple_field && matches!(p.nth(1), T![ident])) {
|
||||||
|
p.bump(T!['(']);
|
||||||
|
paths::use_path(p);
|
||||||
|
p.expect(T![')']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// test crate_visibility_in
|
// test crate_visibility_in
|
||||||
// pub(in super::A) struct S;
|
// pub(in super::A) struct S;
|
||||||
|
|
|
@ -87,7 +87,7 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool) {
|
||||||
pub(super) fn opt_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
|
pub(super) fn opt_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
|
||||||
// test_err pub_expr
|
// test_err pub_expr
|
||||||
// fn foo() { pub 92; }
|
// fn foo() { pub 92; }
|
||||||
let has_visibility = opt_visibility(p);
|
let has_visibility = opt_visibility(p, false);
|
||||||
|
|
||||||
let m = match opt_item_without_modifiers(p, m) {
|
let m = match opt_item_without_modifiers(p, m) {
|
||||||
Ok(()) => return Ok(()),
|
Ok(()) => return Ok(()),
|
||||||
|
|
|
@ -128,7 +128,7 @@ pub(crate) fn record_field_list(p: &mut Parser) {
|
||||||
// test record_field_attrs
|
// test record_field_attrs
|
||||||
// struct S { #[attr] f: f32 }
|
// struct S { #[attr] f: f32 }
|
||||||
attributes::outer_attrs(p);
|
attributes::outer_attrs(p);
|
||||||
opt_visibility(p);
|
opt_visibility(p, false);
|
||||||
if p.at(IDENT) {
|
if p.at(IDENT) {
|
||||||
name(p);
|
name(p);
|
||||||
p.expect(T![:]);
|
p.expect(T![:]);
|
||||||
|
@ -150,7 +150,7 @@ fn tuple_field_list(p: &mut Parser) {
|
||||||
// test tuple_field_attrs
|
// test tuple_field_attrs
|
||||||
// struct S (#[attr] f32);
|
// struct S (#[attr] f32);
|
||||||
attributes::outer_attrs(p);
|
attributes::outer_attrs(p);
|
||||||
opt_visibility(p);
|
opt_visibility(p, true);
|
||||||
if !p.at_ts(types::TYPE_FIRST) {
|
if !p.at_ts(types::TYPE_FIRST) {
|
||||||
p.error("expected a type");
|
p.error("expected a type");
|
||||||
m.complete(p, ERROR);
|
m.complete(p, ERROR);
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
SOURCE_FILE@0..33
|
||||||
|
STRUCT@0..32
|
||||||
|
STRUCT_KW@0..6 "struct"
|
||||||
|
WHITESPACE@6..7 " "
|
||||||
|
NAME@7..15
|
||||||
|
IDENT@7..15 "MyStruct"
|
||||||
|
TUPLE_FIELD_LIST@15..31
|
||||||
|
L_PAREN@15..16 "("
|
||||||
|
TUPLE_FIELD@16..30
|
||||||
|
VISIBILITY@16..19
|
||||||
|
PUB_KW@16..19 "pub"
|
||||||
|
WHITESPACE@19..20 " "
|
||||||
|
TUPLE_TYPE@20..30
|
||||||
|
L_PAREN@20..21 "("
|
||||||
|
PATH_TYPE@21..24
|
||||||
|
PATH@21..24
|
||||||
|
PATH_SEGMENT@21..24
|
||||||
|
NAME_REF@21..24
|
||||||
|
IDENT@21..24 "u32"
|
||||||
|
COMMA@24..25 ","
|
||||||
|
WHITESPACE@25..26 " "
|
||||||
|
PATH_TYPE@26..29
|
||||||
|
PATH@26..29
|
||||||
|
PATH_SEGMENT@26..29
|
||||||
|
NAME_REF@26..29
|
||||||
|
IDENT@26..29 "u32"
|
||||||
|
R_PAREN@29..30 ")"
|
||||||
|
R_PAREN@30..31 ")"
|
||||||
|
SEMICOLON@31..32 ";"
|
||||||
|
WHITESPACE@32..33 "\n"
|
|
@ -0,0 +1 @@
|
||||||
|
struct MyStruct(pub (u32, u32));
|
Loading…
Reference in a new issue