=====================
The unit type
=====================

type A = ();

---

(source_file
  (type_item (type_identifier) (unit_type)))

=====================
Tuple types
=====================

type A = (i32, String);

---

(source_file
  (type_item (type_identifier) (tuple_type (primitive_type) (type_identifier))))

=====================
Reference types
=====================

type A = &B;
type C = &'a str;
type D = &'a mut str;

---

(source_file
  (type_item (type_identifier) (reference_type (type_identifier)))
  (type_item (type_identifier) (reference_type (lifetime (identifier)) (primitive_type)))
  (type_item (type_identifier) (reference_type (lifetime (identifier)) (mutable_specifier) (primitive_type))))

=====================
Raw pointer types
=====================

type A = *mut B;
type C = *const str;

---

(source_file
  (type_item (type_identifier) (pointer_type (mutable_specifier) (type_identifier)))
  (type_item (type_identifier) (pointer_type  (primitive_type))))

=====================
Generic types
=====================

type A = B<C>;
type D = E<F, str>;
type G = H<'a, I>;
type J = H<K=L>;

---

(source_file
  (type_item
    (type_identifier)
    (generic_type (type_identifier) (type_arguments (type_identifier))))
  (type_item
    (type_identifier)
    (generic_type (type_identifier) (type_arguments (type_identifier) (primitive_type))))
  (type_item
    (type_identifier)
    (generic_type (type_identifier) (type_arguments (lifetime (identifier)) (type_identifier))))
  (type_item
    (type_identifier)
    (generic_type (type_identifier) (type_arguments (type_binding (type_identifier) (type_identifier))))))

=====================
Scoped types
=====================

type A = B::C;
type D = E::F::G;
type H = I::J<K>;
type L = M<N>::O;

---

(source_file
  (type_item
    (type_identifier)
    (scoped_type_identifier (identifier) (type_identifier)))
  (type_item
    (type_identifier)
    (scoped_type_identifier (scoped_identifier (identifier) (identifier)) (type_identifier)))
  (type_item
    (type_identifier)
    (generic_type
      (scoped_type_identifier (identifier) (type_identifier))
      (type_arguments (type_identifier))))
  (type_item
    (type_identifier)
    (scoped_type_identifier
      (generic_type (type_identifier) (type_arguments (type_identifier)))
      (type_identifier))))

=====================
Array types
=====================

type A = [B; 4];
type C = &[D];

---

(source_file
  (type_item (type_identifier) (array_type (type_identifier) (integer_literal)))
  (type_item (type_identifier) (reference_type (array_type (type_identifier)))))

============================
Function types
============================

fn high_order1(value: i32, f: fn(i32)) -> i32 {}

fn high_order2(value: i32, f: fn(i32) -> i32) -> i32 {
    f(value)
}

fn high_order3(value: i32, f: &FnOnce(i32) -> i32) -> i32 {
    f(value)
}

type F = for<'a, 'b> fn(x: &'a A, y: &'a mut B<'i, 't>,) -> C;

---

(source_file
  (function_item
    (identifier)
    (parameters
      (parameter (identifier) (primitive_type))
      (parameter (identifier) (function_type (parameters (primitive_type)))))
    (primitive_type)
    (block))
  (function_item
    (identifier)
    (parameters
      (parameter (identifier) (primitive_type))
      (parameter (identifier) (function_type (parameters (primitive_type)) (primitive_type))))
    (primitive_type)
    (block (call_expression (identifier) (arguments (identifier)))))
  (function_item
    (identifier)
    (parameters
      (parameter (identifier) (primitive_type))
      (parameter (identifier) (reference_type (function_type (type_identifier) (parameters (primitive_type)) (primitive_type)))))
    (primitive_type) (block (call_expression (identifier) (arguments (identifier)))))
  (type_item
    (type_identifier)
    (function_type
      (for_lifetimes (lifetime (identifier)) (lifetime (identifier)))
      (parameters (parameter (identifier) (reference_type (lifetime (identifier)) (type_identifier))) (parameter (identifier) (reference_type (lifetime (identifier)) (mutable_specifier) (generic_type (type_identifier) (type_arguments (lifetime (identifier)) (lifetime (identifier)))))))
      (type_identifier))))

=================================
Unsafe and extern function types
=================================

type a = extern "C" fn(*mut c_void);
type b = unsafe extern "C" fn() -> *mut c_void;

---

(source_file
  (type_item
    (type_identifier)
    (function_type
      (function_modifiers (extern_modifier (string_literal)))
      (parameters (pointer_type (mutable_specifier) (type_identifier)))))
  (type_item
    (type_identifier)
    (function_type
      (function_modifiers (extern_modifier (string_literal)))
      (parameters)
      (pointer_type (mutable_specifier) (type_identifier)))))

===================================
Trait objects
===================================

type a = Box<Something + 'a>;
type b = Rc<dyn Something>;
type c = A<&dyn Fn(&B) -> C>;

---

(source_file
  (type_item
    (type_identifier)
    (generic_type
      (type_identifier)
      (type_arguments (bounded_type (type_identifier) (lifetime (identifier))))))
  (type_item
    (type_identifier)
    (generic_type
      (type_identifier)
      (type_arguments (dynamic_type (type_identifier)))))
  (type_item
    (type_identifier)
    (generic_type
      (type_identifier)
      (type_arguments
        (reference_type
          (dynamic_type (function_type (type_identifier) (parameters (reference_type (type_identifier))) (type_identifier))))))))

====================================
Type cast expressions with generics
====================================

a as B<C>;
d as *mut E<<F as E>::G>;

---

(source_file
  (type_cast_expression
    (identifier)
    (generic_type (type_identifier) (type_arguments (type_identifier))))
  (type_cast_expression
    (identifier)
    (pointer_type
      (mutable_specifier)
      (generic_type
        (type_identifier)
        (type_arguments
          (scoped_type_identifier
            (bracketed_type (qualified_type (type_identifier) (type_identifier)))
          (type_identifier)))))))
