From 2389cf96dd07d8c94da349b10f6f2b750707dfd9 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sun, 11 Feb 2018 11:01:00 +0300
Subject: G: Never type

---
 src/parser/grammar/items/consts.rs  |  2 +-
 src/parser/grammar/items/mod.rs     |  2 +-
 src/parser/grammar/items/structs.rs |  4 ++--
 src/parser/grammar/type_params.rs   |  2 +-
 src/parser/grammar/types.rs         | 18 ++++++++++++++----
 5 files changed, 19 insertions(+), 9 deletions(-)

(limited to 'src/parser/grammar')

diff --git a/src/parser/grammar/items/consts.rs b/src/parser/grammar/items/consts.rs
index 5f3cf58c2..d6c3753b3 100644
--- a/src/parser/grammar/items/consts.rs
+++ b/src/parser/grammar/items/consts.rs
@@ -14,7 +14,7 @@ fn const_or_static(p: &mut Parser, kw: SyntaxKind) {
     p.eat(MUT_KW); // TODO: validator to forbid const mut
     name(p);
     p.expect(COLON);
-    types::ty(p);
+    types::type_(p);
     p.expect(EQ);
     expressions::expr(p);
     p.expect(SEMI);
diff --git a/src/parser/grammar/items/mod.rs b/src/parser/grammar/items/mod.rs
index f1776e0e2..b1edf2f22 100644
--- a/src/parser/grammar/items/mod.rs
+++ b/src/parser/grammar/items/mod.rs
@@ -247,7 +247,7 @@ fn type_item(p: &mut Parser) {
     type_params::where_clause(p);
 
     p.expect(EQ);
-    types::ty(p);
+    types::type_(p);
     p.expect(SEMI);
 }
 
diff --git a/src/parser/grammar/items/structs.rs b/src/parser/grammar/items/structs.rs
index ad18fd270..c72b50808 100644
--- a/src/parser/grammar/items/structs.rs
+++ b/src/parser/grammar/items/structs.rs
@@ -89,7 +89,7 @@ fn named_fields(p: &mut Parser) {
         if p.at(IDENT) {
             name(p);
             p.expect(COLON);
-            types::ty(p);
+            types::type_(p);
             field.complete(p, NAMED_FIELD);
         } else {
             field.abandon(p);
@@ -105,7 +105,7 @@ fn pos_fields(p: &mut Parser) {
     while !p.at(R_PAREN) && !p.at(EOF) {
         let pos_field = p.start();
         visibility(p);
-        types::ty(p);
+        types::type_(p);
         pos_field.complete(p, POS_FIELD);
 
         if !p.at(R_PAREN) {
diff --git a/src/parser/grammar/type_params.rs b/src/parser/grammar/type_params.rs
index 2462b260e..9ea08a55c 100644
--- a/src/parser/grammar/type_params.rs
+++ b/src/parser/grammar/type_params.rs
@@ -62,7 +62,7 @@ pub(super) fn list(p: &mut Parser) {
             }
         }
         if p.at(EQ) {
-            types::ty(p)
+            types::type_(p)
         }
         m.complete(p, TYPE_PARAM);
     }
diff --git a/src/parser/grammar/types.rs b/src/parser/grammar/types.rs
index 71801d8ef..2ae583bd1 100644
--- a/src/parser/grammar/types.rs
+++ b/src/parser/grammar/types.rs
@@ -1,8 +1,9 @@
 use super::*;
 
-pub(super) fn ty(p: &mut Parser) {
+pub(super) fn type_(p: &mut Parser) {
     match p.current() {
-        L_PAREN => paren_or_tuple_ty(p),
+        L_PAREN => paren_or_tuple_type(p),
+        EXCL => never_type(p),
         IDENT => path_type(p),
         _ => {
             p.error("expected type");
@@ -10,7 +11,7 @@ pub(super) fn ty(p: &mut Parser) {
     }
 }
 
-fn paren_or_tuple_ty(p: &mut Parser) {
+fn paren_or_tuple_type(p: &mut Parser) {
     assert!(p.at(L_PAREN));
     let m = p.start();
     p.bump();
@@ -18,7 +19,7 @@ fn paren_or_tuple_ty(p: &mut Parser) {
     let mut trailing_comma: bool = false;
     while !p.at(EOF) && !p.at(R_PAREN) {
         n_types += 1;
-        ty(p);
+        type_(p);
         if p.eat(COMMA) {
             trailing_comma = true;
         } else {
@@ -43,6 +44,15 @@ fn paren_or_tuple_ty(p: &mut Parser) {
     m.complete(p, kind);
 }
 
+// test never_type
+// type Never = !;
+fn never_type(p: &mut Parser) {
+    assert!(p.at(EXCL));
+    let m = p.start();
+    p.bump();
+    m.complete(p, NEVER_TYPE);
+}
+
 fn path_type(p: &mut Parser) {
     assert!(p.at(IDENT));
     let m = p.start();
-- 
cgit v1.2.3


From ceb94ece2aa6a1b54063c582663fff4c1937d989 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sun, 11 Feb 2018 11:19:54 +0300
Subject: G: pointer types

---
 src/parser/grammar/types.rs | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

(limited to 'src/parser/grammar')

diff --git a/src/parser/grammar/types.rs b/src/parser/grammar/types.rs
index 2ae583bd1..ceadf5f96 100644
--- a/src/parser/grammar/types.rs
+++ b/src/parser/grammar/types.rs
@@ -4,6 +4,7 @@ pub(super) fn type_(p: &mut Parser) {
     match p.current() {
         L_PAREN => paren_or_tuple_type(p),
         EXCL => never_type(p),
+        STAR => pointer_type(p),
         IDENT => path_type(p),
         _ => {
             p.error("expected type");
@@ -11,6 +12,10 @@ pub(super) fn type_(p: &mut Parser) {
     }
 }
 
+fn type_no_plus(p: &mut Parser) {
+    type_(p);
+}
+
 fn paren_or_tuple_type(p: &mut Parser) {
     assert!(p.at(L_PAREN));
     let m = p.start();
@@ -53,6 +58,30 @@ fn never_type(p: &mut Parser) {
     m.complete(p, NEVER_TYPE);
 }
 
+fn pointer_type(p: &mut Parser) {
+    assert!(p.at(STAR));
+    let m = p.start();
+    p.bump();
+
+    match p.current() {
+        // test pointer_type_mut
+        // type M = *mut ();
+        // type C = *mut ();
+        MUT_KW | CONST_KW => p.bump(),
+        _ => {
+            // test pointer_type_no_mutability
+            // type T = *();
+            p.error(
+                "expected mut or const in raw pointer type \
+                (use `*mut T` or `*const T` as appropriate)"
+            );
+        }
+    };
+
+    type_no_plus(p);
+    m.complete(p, POINTER_TYPE);
+}
+
 fn path_type(p: &mut Parser) {
     assert!(p.at(IDENT));
     let m = p.start();
-- 
cgit v1.2.3


From 555c4ae37560493fd901aad41951ad1664043459 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sun, 11 Feb 2018 11:37:08 +0300
Subject: G: slice & array types

---
 src/parser/grammar/types.rs | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

(limited to 'src/parser/grammar')

diff --git a/src/parser/grammar/types.rs b/src/parser/grammar/types.rs
index ceadf5f96..4eb333b54 100644
--- a/src/parser/grammar/types.rs
+++ b/src/parser/grammar/types.rs
@@ -5,6 +5,7 @@ pub(super) fn type_(p: &mut Parser) {
         L_PAREN => paren_or_tuple_type(p),
         EXCL => never_type(p),
         STAR => pointer_type(p),
+        L_BRACK => array_or_slice_type(p),
         IDENT => path_type(p),
         _ => {
             p.error("expected type");
@@ -82,6 +83,38 @@ fn pointer_type(p: &mut Parser) {
     m.complete(p, POINTER_TYPE);
 }
 
+fn array_or_slice_type(p: &mut Parser) {
+    assert!(p.at(L_BRACK));
+    let m = p.start();
+    p.bump();
+
+    type_(p);
+    let kind = match p.current() {
+        // test slice_type
+        // type T = [()];
+        R_BRACK => {
+            p.bump();
+            SLICE_TYPE
+        },
+
+        // test array_type
+        // type T = [(); 92];
+        SEMI => {
+            p.bump();
+            expressions::expr(p);
+            p.expect(R_BRACK);
+            ARRAY_TYPE
+        }
+        // test array_type_missing_semi
+        // type T = [() 92];
+        _ => {
+            p.error("expected `;` or `]`");
+            SLICE_TYPE
+        }
+    };
+    m.complete(p, kind);
+}
+
 fn path_type(p: &mut Parser) {
     assert!(p.at(IDENT));
     let m = p.start();
-- 
cgit v1.2.3


From eb4c05d572ff0c4e92452232d6591d7a2796e785 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sun, 11 Feb 2018 11:54:09 +0300
Subject: G: reference types

---
 src/parser/grammar/types.rs | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

(limited to 'src/parser/grammar')

diff --git a/src/parser/grammar/types.rs b/src/parser/grammar/types.rs
index 4eb333b54..003341db5 100644
--- a/src/parser/grammar/types.rs
+++ b/src/parser/grammar/types.rs
@@ -6,6 +6,7 @@ pub(super) fn type_(p: &mut Parser) {
         EXCL => never_type(p),
         STAR => pointer_type(p),
         L_BRACK => array_or_slice_type(p),
+        AMPERSAND => reference_type(p),
         IDENT => path_type(p),
         _ => {
             p.error("expected type");
@@ -115,6 +116,20 @@ fn array_or_slice_type(p: &mut Parser) {
     m.complete(p, kind);
 }
 
+// test reference_type;
+// type A = &();
+// type B = &'static ();
+// type C = &mut ();
+fn reference_type(p: &mut Parser) {
+    assert!(p.at(AMPERSAND));
+    let m = p.start();
+    p.bump();
+    p.eat(LIFETIME);
+    p.eat(MUT_KW);
+    type_no_plus(p);
+    m.complete(p, REFERENCE_TYPE);
+}
+
 fn path_type(p: &mut Parser) {
     assert!(p.at(IDENT));
     let m = p.start();
-- 
cgit v1.2.3


From 2fb33b2d0d14f09ee06a42bca252dccbf57185e1 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sun, 11 Feb 2018 11:57:05 +0300
Subject: G: placeholder types

---
 src/parser/grammar/types.rs | 10 ++++++++++
 1 file changed, 10 insertions(+)

(limited to 'src/parser/grammar')

diff --git a/src/parser/grammar/types.rs b/src/parser/grammar/types.rs
index 003341db5..37b74bfe7 100644
--- a/src/parser/grammar/types.rs
+++ b/src/parser/grammar/types.rs
@@ -7,6 +7,7 @@ pub(super) fn type_(p: &mut Parser) {
         STAR => pointer_type(p),
         L_BRACK => array_or_slice_type(p),
         AMPERSAND => reference_type(p),
+        UNDERSCORE => placeholder_type(p),
         IDENT => path_type(p),
         _ => {
             p.error("expected type");
@@ -130,6 +131,15 @@ fn reference_type(p: &mut Parser) {
     m.complete(p, REFERENCE_TYPE);
 }
 
+// test placeholder_type
+// type Placeholder = _;
+fn placeholder_type(p: &mut Parser) {
+    assert!(p.at(UNDERSCORE));
+    let m = p.start();
+    p.bump();
+    m.complete(p, PLACEHOLDER_TYPE);
+}
+
 fn path_type(p: &mut Parser) {
     assert!(p.at(IDENT));
     let m = p.start();
-- 
cgit v1.2.3


From 8a3f17a4e263781deac5e503ad5116ec78004618 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sun, 11 Feb 2018 12:51:09 +0300
Subject: G: fn pointer type

---
 src/parser/grammar/items/mod.rs | 17 -----------------
 src/parser/grammar/mod.rs       | 24 ++++++++++++++++++++++++
 src/parser/grammar/types.rs     | 26 ++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 17 deletions(-)

(limited to 'src/parser/grammar')

diff --git a/src/parser/grammar/items/mod.rs b/src/parser/grammar/items/mod.rs
index b1edf2f22..18ee8af86 100644
--- a/src/parser/grammar/items/mod.rs
+++ b/src/parser/grammar/items/mod.rs
@@ -222,12 +222,6 @@ fn fn_item(p: &mut Parser) {
         p.expect(L_CURLY);
         p.expect(R_CURLY);
     }
-
-    fn fn_value_parameters(p: &mut Parser) {
-        assert!(p.at(L_PAREN));
-        p.bump();
-        p.expect(R_PAREN);
-    }
 }
 
 // test type_item
@@ -263,14 +257,3 @@ fn mod_item(p: &mut Parser) {
         }
     }
 }
-
-fn abi(p: &mut Parser) {
-    assert!(p.at(EXTERN_KW));
-    let abi = p.start();
-    p.bump();
-    match p.current() {
-        STRING | RAW_STRING => p.bump(),
-        _ => (),
-    }
-    abi.complete(p, ABI);
-}
diff --git a/src/parser/grammar/mod.rs b/src/parser/grammar/mod.rs
index abf9fe86c..5266354c1 100644
--- a/src/parser/grammar/mod.rs
+++ b/src/parser/grammar/mod.rs
@@ -50,6 +50,30 @@ fn alias(p: &mut Parser) -> bool {
     true //FIXME: return false if three are errors
 }
 
+fn abi(p: &mut Parser) {
+    assert!(p.at(EXTERN_KW));
+    let abi = p.start();
+    p.bump();
+    match p.current() {
+        STRING | RAW_STRING => p.bump(),
+        _ => (),
+    }
+    abi.complete(p, ABI);
+}
+
+fn fn_value_parameters(p: &mut Parser) {
+    assert!(p.at(L_PAREN));
+    p.bump();
+    p.expect(R_PAREN);
+}
+
+fn fn_ret_type(p: &mut Parser) {
+    if p.at(THIN_ARROW) {
+        p.bump();
+        types::type_(p);
+    }
+}
+
 fn name(p: &mut Parser) {
     if p.at(IDENT) {
         let m = p.start();
diff --git a/src/parser/grammar/types.rs b/src/parser/grammar/types.rs
index 37b74bfe7..ea4df8639 100644
--- a/src/parser/grammar/types.rs
+++ b/src/parser/grammar/types.rs
@@ -8,6 +8,7 @@ pub(super) fn type_(p: &mut Parser) {
         L_BRACK => array_or_slice_type(p),
         AMPERSAND => reference_type(p),
         UNDERSCORE => placeholder_type(p),
+        FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p),
         IDENT => path_type(p),
         _ => {
             p.error("expected type");
@@ -140,6 +141,31 @@ fn placeholder_type(p: &mut Parser) {
     m.complete(p, PLACEHOLDER_TYPE);
 }
 
+// test fn_pointer_type
+// type A = fn();
+// type B = unsafe fn();
+// type C = unsafe extern "C" fn();
+fn fn_pointer_type(p: &mut Parser) {
+    let m = p.start();
+    p.eat(UNSAFE_KW);
+    if p.at(EXTERN_KW) {
+        abi(p);
+    }
+    // test fn_pointer_type_missing_fn
+    // type F = unsafe ();
+    if !p.eat(FN_KW) {
+        m.abandon(p);
+        p.error("expected `fn`");
+        return;
+    }
+
+    fn_value_parameters(p);
+    // test fn_pointer_type_with_ret
+    // type F = fn() -> ();
+    fn_ret_type(p);
+    m.complete(p, FN_POINTER_TYPE);
+}
+
 fn path_type(p: &mut Parser) {
     assert!(p.at(IDENT));
     let m = p.start();
-- 
cgit v1.2.3


From 96437b050f2743fef2e37eaab7259f2f98f9b473 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sun, 11 Feb 2018 12:58:12 +0300
Subject: Formatting

---
 src/parser/grammar/types.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/parser/grammar')

diff --git a/src/parser/grammar/types.rs b/src/parser/grammar/types.rs
index ea4df8639..a4967a00a 100644
--- a/src/parser/grammar/types.rs
+++ b/src/parser/grammar/types.rs
@@ -77,7 +77,7 @@ fn pointer_type(p: &mut Parser) {
             // type T = *();
             p.error(
                 "expected mut or const in raw pointer type \
-                (use `*mut T` or `*const T` as appropriate)"
+                 (use `*mut T` or `*const T` as appropriate)",
             );
         }
     };
@@ -98,7 +98,7 @@ fn array_or_slice_type(p: &mut Parser) {
         R_BRACK => {
             p.bump();
             SLICE_TYPE
-        },
+        }
 
         // test array_type
         // type T = [(); 92];
-- 
cgit v1.2.3