@@ -28,35 +28,46 @@ impl<'a> Parser<'a> {
2828 /// Parses a source module as a crate. This is the main entry point for the parser.
2929 pub fn parse_crate_mod ( & mut self ) -> PResult < ' a , ast:: Crate > {
3030 let lo = self . token . span ;
31- let ( module, attrs) = self . parse_mod ( & token:: Eof ) ?;
31+ let ( module, attrs) = self . parse_mod ( & token:: Eof , Unsafe :: No ) ?;
3232 let span = lo. to ( self . token . span ) ;
3333 let proc_macros = Vec :: new ( ) ; // Filled in by `proc_macro_harness::inject()`.
3434 Ok ( ast:: Crate { attrs, module, span, proc_macros } )
3535 }
3636
3737 /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
3838 fn parse_item_mod ( & mut self , attrs : & mut Vec < Attribute > ) -> PResult < ' a , ItemInfo > {
39+ let unsafety = self . parse_unsafety ( ) ;
40+ self . expect_keyword ( kw:: Mod ) ?;
3941 let id = self . parse_ident ( ) ?;
4042 let ( module, mut inner_attrs) = if self . eat ( & token:: Semi ) {
41- Default :: default ( )
43+ ( Mod { inner : Span :: default ( ) , unsafety , items : Vec :: new ( ) , inline : false } , Vec :: new ( ) )
4244 } else {
4345 self . expect ( & token:: OpenDelim ( token:: Brace ) ) ?;
44- self . parse_mod ( & token:: CloseDelim ( token:: Brace ) ) ?
46+ self . parse_mod ( & token:: CloseDelim ( token:: Brace ) , unsafety ) ?
4547 } ;
4648 attrs. append ( & mut inner_attrs) ;
4749 Ok ( ( id, ItemKind :: Mod ( module) ) )
4850 }
4951
5052 /// Parses the contents of a module (inner attributes followed by module items).
51- pub fn parse_mod ( & mut self , term : & TokenKind ) -> PResult < ' a , ( Mod , Vec < Attribute > ) > {
53+ pub fn parse_mod (
54+ & mut self ,
55+ term : & TokenKind ,
56+ unsafety : Unsafe ,
57+ ) -> PResult < ' a , ( Mod , Vec < Attribute > ) > {
5258 let lo = self . token . span ;
5359 let attrs = self . parse_inner_attributes ( ) ?;
54- let module = self . parse_mod_items ( term, lo) ?;
60+ let module = self . parse_mod_items ( term, lo, unsafety ) ?;
5561 Ok ( ( module, attrs) )
5662 }
5763
5864 /// Given a termination token, parses all of the items in a module.
59- fn parse_mod_items ( & mut self , term : & TokenKind , inner_lo : Span ) -> PResult < ' a , Mod > {
65+ fn parse_mod_items (
66+ & mut self ,
67+ term : & TokenKind ,
68+ inner_lo : Span ,
69+ unsafety : Unsafe ,
70+ ) -> PResult < ' a , Mod > {
6071 let mut items = vec ! [ ] ;
6172 while let Some ( item) = self . parse_item ( ) ? {
6273 items. push ( item) ;
@@ -75,7 +86,7 @@ impl<'a> Parser<'a> {
7586
7687 let hi = if self . token . span . is_dummy ( ) { inner_lo } else { self . prev_token . span } ;
7788
78- Ok ( Mod { inner : inner_lo. to ( hi) , items, inline : true } )
89+ Ok ( Mod { inner : inner_lo. to ( hi) , unsafety , items, inline : true } )
7990 }
8091}
8192
@@ -235,8 +246,13 @@ impl<'a> Parser<'a> {
235246 self . parse_item_extern_crate ( ) ?
236247 } else {
237248 // EXTERN BLOCK
238- self . parse_item_foreign_mod ( attrs) ?
249+ self . parse_item_foreign_mod ( attrs, Unsafe :: No ) ?
239250 }
251+ } else if self . is_unsafe_foreign_mod ( ) {
252+ // EXTERN BLOCK
253+ let unsafety = self . parse_unsafety ( ) ;
254+ self . expect_keyword ( kw:: Extern ) ?;
255+ self . parse_item_foreign_mod ( attrs, unsafety) ?
240256 } else if self . is_static_global ( ) {
241257 // STATIC ITEM
242258 self . bump ( ) ; // `static`
@@ -256,7 +272,9 @@ impl<'a> Parser<'a> {
256272 {
257273 // IMPL ITEM
258274 self . parse_item_impl ( attrs, def ( ) ) ?
259- } else if self . eat_keyword ( kw:: Mod ) {
275+ } else if self . check_keyword ( kw:: Mod )
276+ || self . check_keyword ( kw:: Unsafe ) && self . is_keyword_ahead ( 1 , & [ kw:: Mod ] )
277+ {
260278 // MODULE ITEM
261279 self . parse_item_mod ( attrs) ?
262280 } else if self . eat_keyword ( kw:: Type ) {
@@ -893,10 +911,14 @@ impl<'a> Parser<'a> {
893911 /// extern "C" {}
894912 /// extern {}
895913 /// ```
896- fn parse_item_foreign_mod ( & mut self , attrs : & mut Vec < Attribute > ) -> PResult < ' a , ItemInfo > {
914+ fn parse_item_foreign_mod (
915+ & mut self ,
916+ attrs : & mut Vec < Attribute > ,
917+ unsafety : Unsafe ,
918+ ) -> PResult < ' a , ItemInfo > {
897919 let abi = self . parse_abi ( ) ; // ABI?
898920 let items = self . parse_item_list ( attrs, |p| p. parse_foreign_item ( ) ) ?;
899- let module = ast:: ForeignMod { abi, items } ;
921+ let module = ast:: ForeignMod { unsafety , abi, items } ;
900922 Ok ( ( Ident :: invalid ( ) , ItemKind :: ForeignMod ( module) ) )
901923 }
902924
@@ -938,6 +960,15 @@ impl<'a> Parser<'a> {
938960 . emit ( ) ;
939961 }
940962
963+ fn is_unsafe_foreign_mod ( & self ) -> bool {
964+ self . token . is_keyword ( kw:: Unsafe )
965+ && self . is_keyword_ahead ( 1 , & [ kw:: Extern ] )
966+ && self . look_ahead (
967+ 2 + self . look_ahead ( 2 , |t| t. can_begin_literal_maybe_minus ( ) as usize ) ,
968+ |t| t. kind == token:: OpenDelim ( token:: Brace ) ,
969+ )
970+ }
971+
941972 fn is_static_global ( & mut self ) -> bool {
942973 if self . check_keyword ( kw:: Static ) {
943974 // Check if this could be a closure.
@@ -1552,10 +1583,14 @@ impl<'a> Parser<'a> {
15521583 // `$qual fn` or `$qual $qual`:
15531584 || QUALS . iter ( ) . any ( |& kw| self . check_keyword ( kw) )
15541585 && self . look_ahead ( 1 , |t| {
1555- // ...qualified and then ` fn`, e.g. `const fn`.
1586+ // `$qual fn`, e.g. `const fn` or `async fn`.
15561587 t. is_keyword ( kw:: Fn )
1557- // Two qualifiers. This is enough. Due `async` we need to check that it's reserved.
1558- || t. is_non_raw_ident_where ( |i| QUALS . contains ( & i. name ) && i. is_reserved ( ) )
1588+ // Two qualifiers `$qual $qual` is enough, e.g. `async unsafe`.
1589+ || t. is_non_raw_ident_where ( |i| QUALS . contains ( & i. name )
1590+ // Rule out 2015 `const async: T = val`.
1591+ && i. is_reserved ( )
1592+ // Rule out unsafe extern block.
1593+ && !self . is_unsafe_foreign_mod ( ) )
15591594 } )
15601595 // `extern ABI fn`
15611596 || self . check_keyword ( kw:: Extern )
@@ -1567,9 +1602,9 @@ impl<'a> Parser<'a> {
15671602 /// up to and including the `fn` keyword. The formal grammar is:
15681603 ///
15691604 /// ```
1570- /// Extern = "extern" StringLit ;
1605+ /// Extern = "extern" StringLit? ;
15711606 /// FnQual = "const"? "async"? "unsafe"? Extern? ;
1572- /// FnFrontMatter = FnQual? "fn" ;
1607+ /// FnFrontMatter = FnQual "fn" ;
15731608 /// ```
15741609 pub ( super ) fn parse_fn_front_matter ( & mut self ) -> PResult < ' a , FnHeader > {
15751610 let constness = self . parse_constness ( ) ;
0 commit comments