elm_ast/type_annotation.rs
1use crate::ident::{Ident, ModuleName};
2use crate::node::Spanned;
3
4/// A type annotation in Elm source code.
5///
6/// Represents the syntax of types as written by the programmer, before any
7/// resolution or canonicalization.
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub enum TypeAnnotation {
11 /// A type variable: `a`, `msg`, `comparable`
12 GenericType(Ident),
13
14 /// A named type, possibly qualified, with type arguments.
15 ///
16 /// Examples:
17 /// - `Int` → `Typed { module_name: [], name: "Int", args: [] }`
18 /// - `Maybe Int` → `Typed { module_name: [], name: "Maybe", args: [Int] }`
19 /// - `Dict.Dict String Int` → `Typed { module_name: ["Dict"], name: "Dict", args: [String, Int] }`
20 Typed {
21 module_name: ModuleName,
22 name: Spanned<Ident>,
23 args: Vec<Spanned<TypeAnnotation>>,
24 },
25
26 /// The unit type: `()`
27 Unit,
28
29 /// A tuple type: `( Int, String )` or `( Int, String, Bool )`
30 ///
31 /// Elm only supports 2-tuples and 3-tuples.
32 Tupled(Vec<Spanned<TypeAnnotation>>),
33
34 /// A record type: `{ name : String, age : Int }`
35 Record(Vec<Spanned<RecordField>>),
36
37 /// An extensible record type: `{ a | name : String, age : Int }`
38 GenericRecord {
39 base: Spanned<Ident>,
40 fields: Vec<Spanned<RecordField>>,
41 },
42
43 /// A function type: `Int -> String`
44 FunctionType {
45 from: Box<Spanned<TypeAnnotation>>,
46 to: Box<Spanned<TypeAnnotation>>,
47 },
48}
49
50/// A single field in a record type: `name : String`
51#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
52#[derive(Clone, Debug, PartialEq, Eq)]
53pub struct RecordField {
54 pub name: Spanned<Ident>,
55 pub type_annotation: Spanned<TypeAnnotation>,
56}