Skip to main content

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}