@@ -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