@@ -28,35 +28,46 @@ impl<'a> Parser<'a> {
28
28
/// Parses a source module as a crate. This is the main entry point for the parser.
29
29
pub fn parse_crate_mod ( & mut self ) -> PResult < ' a , ast:: Crate > {
30
30
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 ) ?;
32
32
let span = lo. to ( self . token . span ) ;
33
33
let proc_macros = Vec :: new ( ) ; // Filled in by `proc_macro_harness::inject()`.
34
34
Ok ( ast:: Crate { attrs, module, span, proc_macros } )
35
35
}
36
36
37
37
/// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
38
38
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 ) ?;
39
41
let id = self . parse_ident ( ) ?;
40
42
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 ( ) )
42
44
} else {
43
45
self . expect ( & token:: OpenDelim ( token:: Brace ) ) ?;
44
- self . parse_mod ( & token:: CloseDelim ( token:: Brace ) ) ?
46
+ self . parse_mod ( & token:: CloseDelim ( token:: Brace ) , unsafety ) ?
45
47
} ;
46
48
attrs. append ( & mut inner_attrs) ;
47
49
Ok ( ( id, ItemKind :: Mod ( module) ) )
48
50
}
49
51
50
52
/// 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 > ) > {
52
58
let lo = self . token . span ;
53
59
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 ) ?;
55
61
Ok ( ( module, attrs) )
56
62
}
57
63
58
64
/// 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 > {
60
71
let mut items = vec ! [ ] ;
61
72
while let Some ( item) = self . parse_item ( ) ? {
62
73
items. push ( item) ;
@@ -75,7 +86,7 @@ impl<'a> Parser<'a> {
75
86
76
87
let hi = if self . token . span . is_dummy ( ) { inner_lo } else { self . prev_token . span } ;
77
88
78
- Ok ( Mod { inner : inner_lo. to ( hi) , items, inline : true } )
89
+ Ok ( Mod { inner : inner_lo. to ( hi) , unsafety , items, inline : true } )
79
90
}
80
91
}
81
92
@@ -235,8 +246,13 @@ impl<'a> Parser<'a> {
235
246
self . parse_item_extern_crate ( ) ?
236
247
} else {
237
248
// EXTERN BLOCK
238
- self . parse_item_foreign_mod ( attrs) ?
249
+ self . parse_item_foreign_mod ( attrs, Unsafe :: No ) ?
239
250
}
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) ?
240
256
} else if self . is_static_global ( ) {
241
257
// STATIC ITEM
242
258
self . bump ( ) ; // `static`
@@ -256,7 +272,9 @@ impl<'a> Parser<'a> {
256
272
{
257
273
// IMPL ITEM
258
274
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
+ {
260
278
// MODULE ITEM
261
279
self . parse_item_mod ( attrs) ?
262
280
} else if self . eat_keyword ( kw:: Type ) {
@@ -893,10 +911,14 @@ impl<'a> Parser<'a> {
893
911
/// extern "C" {}
894
912
/// extern {}
895
913
/// ```
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 > {
897
919
let abi = self . parse_abi ( ) ; // ABI?
898
920
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 } ;
900
922
Ok ( ( Ident :: invalid ( ) , ItemKind :: ForeignMod ( module) ) )
901
923
}
902
924
@@ -938,6 +960,15 @@ impl<'a> Parser<'a> {
938
960
. emit ( ) ;
939
961
}
940
962
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
+
941
972
fn is_static_global ( & mut self ) -> bool {
942
973
if self . check_keyword ( kw:: Static ) {
943
974
// Check if this could be a closure.
@@ -1552,10 +1583,14 @@ impl<'a> Parser<'a> {
1552
1583
// `$qual fn` or `$qual $qual`:
1553
1584
|| QUALS . iter ( ) . any ( |& kw| self . check_keyword ( kw) )
1554
1585
&& self . look_ahead ( 1 , |t| {
1555
- // ...qualified and then ` fn`, e.g. `const fn`.
1586
+ // `$qual fn`, e.g. `const fn` or `async fn`.
1556
1587
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 ( ) )
1559
1594
} )
1560
1595
// `extern ABI fn`
1561
1596
|| self . check_keyword ( kw:: Extern )
@@ -1567,9 +1602,9 @@ impl<'a> Parser<'a> {
1567
1602
/// up to and including the `fn` keyword. The formal grammar is:
1568
1603
///
1569
1604
/// ```
1570
- /// Extern = "extern" StringLit ;
1605
+ /// Extern = "extern" StringLit? ;
1571
1606
/// FnQual = "const"? "async"? "unsafe"? Extern? ;
1572
- /// FnFrontMatter = FnQual? "fn" ;
1607
+ /// FnFrontMatter = FnQual "fn" ;
1573
1608
/// ```
1574
1609
pub ( super ) fn parse_fn_front_matter ( & mut self ) -> PResult < ' a , FnHeader > {
1575
1610
let constness = self . parse_constness ( ) ;
0 commit comments