}
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 ]
}
}
-fn opt_visibility(p: &mut Parser) -> bool {
+fn opt_visibility(p: &mut Parser, in_tuple_field: bool) -> bool {
match p.current() {
T![pub] => {
let m = p.start();
// struct B(pub (super::A));
// struct B(pub (crate::A,));
T![crate] | T![self] | T![super] | T![ident] if p.nth(2) != T![:] => {
- p.bump(T!['(']);
- paths::use_path(p);
- p.expect(T![')']);
+ // If we are in a tuple struct, then the parens following `pub`
+ // might be an tuple field, not part of the visibility. So in that
+ // 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
// pub(in super::A) struct S;
pub(super) fn opt_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
// test_err pub_expr
// 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) {
Ok(()) => return Ok(()),
// test record_field_attrs
// struct S { #[attr] f: f32 }
attributes::outer_attrs(p);
- opt_visibility(p);
+ opt_visibility(p, false);
if p.at(IDENT) {
name(p);
p.expect(T![:]);
// test tuple_field_attrs
// struct S (#[attr] f32);
attributes::outer_attrs(p);
- opt_visibility(p);
+ opt_visibility(p, true);
if !p.at_ts(types::TYPE_FIRST) {
p.error("expected a type");
m.complete(p, ERROR);