about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-05-06 18:43:56 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-05-06 21:03:59 -0700
commit08237cad8d2ce9287aedf99e57384407cc9dc42d (patch)
treeaca7e5b64833b1216f0a747308533657255e1c1e /src/libsyntax/parse
parentcf6857b9e9427f14d383ae2924555bedc251fa02 (diff)
downloadrust-08237cad8d2ce9287aedf99e57384407cc9dc42d.tar.gz
rust-08237cad8d2ce9287aedf99e57384407cc9dc42d.zip
rustc: Enable writing "unsafe extern fn() {}"
Previously, the parser would not allow you to simultaneously implement a
function with a different abi as well as being unsafe at the same time. This
extends the parser to allow functions of the form:

    unsafe extern fn foo() {
        // ...
    }

The closure type grammar was also changed to reflect this reversal, types
previously written as "extern unsafe fn()" must now be written as
"unsafe extern fn()". The parser currently has a hack which allows the old
style, but this will go away once a snapshot has landed.

Closes #10025

[breaking-change]
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs38
1 files changed, 24 insertions, 14 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 11a773a7f09..ca3bad12700 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -27,7 +27,7 @@ use ast::{ExprLit, ExprLoop, ExprMac};
 use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
 use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
 use ast::{ExprVec, ExprVstore, ExprVstoreSlice};
-use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, ExternFn, Field, FnDecl};
+use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, Field, FnDecl};
 use ast::{ExprVstoreUniq, Once, Many};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
 use ast::{Ident, NormalFn, Inherited, Item, Item_, ItemStatic};
@@ -881,25 +881,29 @@ impl<'a> Parser<'a> {
     pub fn parse_ty_bare_fn(&mut self) -> Ty_ {
         /*
 
-        [extern "ABI"] [unsafe] fn <'lt> (S) -> T
-                ^~~~^  ^~~~~~~^    ^~~~^ ^~^    ^
-                  |      |           |    |     |
-                  |      |           |    |   Return type
-                  |      |           |  Argument types
-                  |      |       Lifetimes
-                  |      |
-                  |    Function Style
-                 ABI
-
+        [unsafe] [extern "ABI"] fn <'lt> (S) -> T
+         ^~~~^           ^~~~^     ^~~~^ ^~^    ^
+           |               |         |    |     |
+           |               |         |    |   Return type
+           |               |         |  Argument types
+           |               |     Lifetimes
+           |              ABI
+        Function Style
         */
 
+        let fn_style = self.parse_unsafety();
         let abi = if self.eat_keyword(keywords::Extern) {
             self.parse_opt_abi().unwrap_or(abi::C)
         } else {
             abi::Rust
         };
 
-        let fn_style = self.parse_unsafety();
+        // NOTE: remove after a stage0 snapshot
+        let fn_style = match self.parse_unsafety() {
+            UnsafeFn => UnsafeFn,
+            NormalFn => fn_style,
+        };
+
         self.expect_keyword(keywords::Fn);
         let (decl, lifetimes) = self.parse_ty_fn_decl(true);
         return TyBareFn(@BareFnTy {
@@ -1245,6 +1249,7 @@ impl<'a> Parser<'a> {
             self.expect_and();
             self.parse_borrowed_pointee()
         } else if self.is_keyword(keywords::Extern) ||
+                  self.is_keyword(keywords::Unsafe) ||
                 self.token_is_bare_fn_keyword() {
             // BARE FUNCTION
             self.parse_ty_bare_fn()
@@ -4551,7 +4556,7 @@ impl<'a> Parser<'a> {
                 // EXTERN FUNCTION ITEM
                 let abi = opt_abi.unwrap_or(abi::C);
                 let (ident, item_, extra_attrs) =
-                    self.parse_item_fn(ExternFn, abi);
+                    self.parse_item_fn(NormalFn, abi);
                 let item = self.mk_item(lo,
                                         self.last_span.hi,
                                         ident,
@@ -4605,9 +4610,14 @@ impl<'a> Parser<'a> {
             && self.look_ahead(1u, |t| *t != token::LBRACE) {
             // UNSAFE FUNCTION ITEM
             self.bump();
+            let abi = if self.eat_keyword(keywords::Extern) {
+                self.parse_opt_abi().unwrap_or(abi::C)
+            } else {
+                abi::Rust
+            };
             self.expect_keyword(keywords::Fn);
             let (ident, item_, extra_attrs) =
-                self.parse_item_fn(UnsafeFn, abi::Rust);
+                self.parse_item_fn(UnsafeFn, abi);
             let item = self.mk_item(lo,
                                     self.last_span.hi,
                                     ident,