Skip to main content

cl_typeck/entry/
display.rs

1use super::*;
2use crate::{format_utils::*, type_kind::Adt};
3use std::fmt::{self, Write};
4
5/// Printing the name of a named type stops infinite recursion
6fn write_name_or(h: Entry, f: &mut impl Write) -> fmt::Result {
7    match h.name() {
8        Some(name) => write!(f, "{name}"),
9        None => write!(f, "{h}"),
10    }
11}
12
13impl fmt::Display for Entry<'_> {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        let Some(&kind) = self.kind() else {
16            return write!(f, "<invalid type: {}>", self.id);
17        };
18
19        if let Some(ty) = self.ty() {
20            match ty {
21                TypeKind::Inferred => write!(f, "<_{}>", self.id),
22                TypeKind::Variable => write!(f, "<?{}>", self.id),
23                TypeKind::Instance(id) => write!(f, "{}", self.with_id(*id)),
24                TypeKind::Primitive(kind) => write!(f, "{kind}"),
25                TypeKind::Adt(adt) => write_adt(adt, self, f),
26                &TypeKind::Ref(id) => {
27                    f.write_str("&")?;
28                    let h_id = self.with_id(id);
29                    write_name_or(h_id, f)
30                }
31                &TypeKind::Ptr(id) => {
32                    f.write_str("*")?;
33                    let h_id = self.with_id(id);
34                    write_name_or(h_id, f)
35                }
36                TypeKind::Slice(id) => write_name_or(self.with_id(*id), &mut f.delimit("[", "]")),
37                &TypeKind::Array(t, cnt) => {
38                    let mut f = f.delimit("[", "]");
39                    write_name_or(self.with_id(t), &mut f)?;
40                    write!(f, "; {cnt}")
41                }
42                TypeKind::Tuple(ids) => {
43                    let mut f = f.delimit("(", ")");
44                    for (index, &id) in ids.iter().enumerate() {
45                        if index > 0 {
46                            write!(f, ", ")?;
47                        }
48                        write_name_or(self.with_id(id), &mut f)?;
49                    }
50                    Ok(())
51                }
52                TypeKind::FnSig { args, rety } => {
53                    write!(f, "fn {} -> ", self.with_id(*args))?;
54                    write_name_or(self.with_id(*rety), f)
55                }
56                TypeKind::Module => write!(f, "module?"),
57            }
58        } else {
59            match kind {
60                NodeKind::Type
61                | NodeKind::Const
62                | NodeKind::Static
63                | NodeKind::Temporary
64                | NodeKind::Let => write!(f, "WARNING: NO TYPE ASSIGNED FOR {}", self.id),
65                _ => write!(f, "{kind}"),
66            }
67        }
68    }
69}
70
71fn write_adt(adt: &Adt, h: &Entry, f: &mut impl Write) -> fmt::Result {
72    match adt {
73        Adt::Enum(variants) => {
74            let mut variants = variants.iter();
75            separate(", ", || {
76                variants.next().map(|(name, def)| {
77                    move |f: &mut Delimit<_>| write!(f, "{name}: {}", h.with_id(*def))
78                })
79            })(f.delimit("enum {", "}"))
80        }
81        Adt::Struct(members) => {
82            let mut members = members.iter();
83            separate(", ", || {
84                let (name, vis, id) = members.next()?;
85                Some(move |f: &mut Delimit<_>| write!(f, "{vis}{name}: {}", h.with_id(*id)))
86            })(f.delimit("struct {", "}"))
87        }
88        Adt::TupleStruct(members) => {
89            let mut members = members.iter();
90            separate(", ", || {
91                let (vis, def) = members.next()?;
92                Some(move |f: &mut Delimit<_>| write!(f, "{vis}{}", h.with_id(*def)))
93            })(f.delimit("struct (", ")"))
94        }
95        Adt::UnitStruct => write!(f, "struct"),
96        Adt::Union(_) => todo!("Display union types"),
97    }
98}