Skip to content

Commit 66bf323

Browse files
committed
syntax: cleanup parse_visibility.
1 parent 5b80ead commit 66bf323

File tree

1 file changed

+69
-53
lines changed

1 file changed

+69
-53
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 69 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,68 +1417,84 @@ impl<'a> Parser<'a> {
14171417
// `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`.
14181418
// Because of this, we only `bump` the `(` if we're assured it is appropriate to do so
14191419
// by the following tokens.
1420-
if self.is_keyword_ahead(1, &[kw::Crate]) &&
1421-
self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)`
1420+
if self.is_keyword_ahead(1, &[kw::Crate])
1421+
&& self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)`
14221422
{
1423-
// `pub(crate)`
1424-
self.bump(); // `(`
1425-
self.bump(); // `crate`
1426-
self.expect(&token::CloseDelim(token::Paren))?; // `)`
1427-
let vis = respan(
1428-
lo.to(self.prev_span),
1429-
VisibilityKind::Crate(CrateSugar::PubCrate),
1430-
);
1431-
return Ok(vis)
1423+
return self.parse_vis_pub_crate(lo);
14321424
} else if self.is_keyword_ahead(1, &[kw::In]) {
1433-
// `pub(in path)`
1434-
self.bump(); // `(`
1435-
self.bump(); // `in`
1436-
let path = self.parse_path(PathStyle::Mod)?; // `path`
1437-
self.expect(&token::CloseDelim(token::Paren))?; // `)`
1438-
let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
1439-
path: P(path),
1440-
id: ast::DUMMY_NODE_ID,
1441-
});
1442-
return Ok(vis)
1443-
} else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) &&
1444-
self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower])
1425+
return self.parse_vis_pub_in(lo);
1426+
} else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren))
1427+
&& self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower])
14451428
{
1446-
// `pub(self)` or `pub(super)`
1447-
self.bump(); // `(`
1448-
let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
1449-
self.expect(&token::CloseDelim(token::Paren))?; // `)`
1450-
let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
1451-
path: P(path),
1452-
id: ast::DUMMY_NODE_ID,
1453-
});
1454-
return Ok(vis)
1455-
} else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct
1456-
// `pub(something) fn ...` or `struct X { pub(something) y: Z }`
1457-
self.bump(); // `(`
1458-
let msg = "incorrect visibility restriction";
1459-
let suggestion = r##"some possible visibility restrictions are:
1460-
`pub(crate)`: visible only on the current crate
1461-
`pub(super)`: visible only in the current module's parent
1462-
`pub(in path::to::module)`: visible only on the specified path"##;
1463-
let path = self.parse_path(PathStyle::Mod)?;
1464-
let sp = path.span;
1465-
let help_msg = format!("make this visible only to module `{}` with `in`", path);
1466-
self.expect(&token::CloseDelim(token::Paren))?; // `)`
1467-
struct_span_err!(self.sess.span_diagnostic, sp, E0704, "{}", msg)
1468-
.help(suggestion)
1469-
.span_suggestion(
1470-
sp,
1471-
&help_msg,
1472-
format!("in {}", path),
1473-
Applicability::MachineApplicable,
1474-
)
1475-
.emit(); // Emit diagnostic, but continue with public visibility.
1429+
return self.parse_vis_self_super(lo);
1430+
} else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct.
1431+
self.recover_incorrect_vis_restriction()?;
1432+
// Emit diagnostic, but continue with public visibility.
14761433
}
14771434
}
14781435

14791436
Ok(respan(lo, VisibilityKind::Public))
14801437
}
14811438

1439+
/// Parse `pub(crate)`.
1440+
fn parse_vis_pub_crate(&mut self, lo: Span) -> PResult<'a, Visibility> {
1441+
self.bump(); // `(`
1442+
self.bump(); // `crate`
1443+
self.expect(&token::CloseDelim(token::Paren))?; // `)`
1444+
Ok(respan(
1445+
lo.to(self.prev_span),
1446+
VisibilityKind::Crate(CrateSugar::PubCrate),
1447+
))
1448+
}
1449+
1450+
/// Parse `pub(in path)`.
1451+
fn parse_vis_pub_in(&mut self, lo: Span) -> PResult<'a, Visibility> {
1452+
self.bump(); // `(`
1453+
self.bump(); // `in`
1454+
let path = self.parse_path(PathStyle::Mod)?; // `path`
1455+
self.expect(&token::CloseDelim(token::Paren))?; // `)`
1456+
Ok(respan(lo.to(self.prev_span), VisibilityKind::Restricted {
1457+
path: P(path),
1458+
id: ast::DUMMY_NODE_ID,
1459+
}))
1460+
}
1461+
1462+
/// Parse `pub(self)` or `pub(super)`.
1463+
fn parse_vis_self_super(&mut self, lo: Span) -> PResult<'a, Visibility> {
1464+
self.bump(); // `(`
1465+
let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
1466+
self.expect(&token::CloseDelim(token::Paren))?; // `)`
1467+
Ok(respan(lo.to(self.prev_span), VisibilityKind::Restricted {
1468+
path: P(path),
1469+
id: ast::DUMMY_NODE_ID,
1470+
}))
1471+
}
1472+
1473+
/// Recovery for e.g. `pub(something) fn ...` or `struct X { pub(something) y: Z }`
1474+
fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> {
1475+
self.bump(); // `(`
1476+
let path = self.parse_path(PathStyle::Mod)?;
1477+
self.expect(&token::CloseDelim(token::Paren))?; // `)`
1478+
1479+
let msg = "incorrect visibility restriction";
1480+
let suggestion = r##"some possible visibility restrictions are:
1481+
`pub(crate)`: visible only on the current crate
1482+
`pub(super)`: visible only in the current module's parent
1483+
`pub(in path::to::module)`: visible only on the specified path"##;
1484+
1485+
struct_span_err!(self.sess.span_diagnostic, path.span, E0704, "{}", msg)
1486+
.help(suggestion)
1487+
.span_suggestion(
1488+
path.span,
1489+
&format!("make this visible only to module `{}` with `in`", path),
1490+
format!("in {}", path),
1491+
Applicability::MachineApplicable,
1492+
)
1493+
.emit();
1494+
1495+
Ok(())
1496+
}
1497+
14821498
/// Parses a string as an ABI spec on an extern type or module. Consumes
14831499
/// the `extern` keyword, if one is found.
14841500
fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {

0 commit comments

Comments
 (0)