diff --git a/src/ast2/intern.rs b/src/ast2/intern.rs
index 6f38e6d..a59aee5 100644
--- a/src/ast2/intern.rs
+++ b/src/ast2/intern.rs
@@ -43,6 +43,7 @@ impl Display for SimpleType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         write!(
             f,
+            "{}",
             match self {
                 SimpleType::F32 => "f32",
                 SimpleType::F64 => "f64",
@@ -151,32 +152,11 @@ pub enum Key<'a> {
     FalseValue,
 }
 
-struct KeyDisplay<'a> {
+pub struct KeyDisplay<'a> {
     ip: &'a InternPool,
     key: Key<'a>,
 }
 
-struct DisplayCommaSep<T: IntoIterator<Item = Display>> {
-    t: T,
-}
-
-impl<T: IntoIterator<Item = Display>> Display for DisplayCommaSep<T> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        let mut iter = self.t.into_iter();
-
-        let Some(ref next) = iter.next() else {
-            return Ok(());
-        };
-        write!(f, "{next}")?;
-
-        for ref item in iter {
-            write!(f, ", {next}")?;
-        }
-
-        Ok(())
-    }
-}
-
 impl Display for KeyDisplay<'_> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self.key {
@@ -188,8 +168,8 @@ impl Display for KeyDisplay<'_> {
             Key::UInt64 { bits } => write!(f, "{bits}")?,
             Key::F32 { bits } => write!(f, "{bits}")?,
             Key::F64 { bits } => write!(f, "{bits}")?,
-            Key::PositiveInt { bigint } => write!(f, "{bigint}")?,
-            Key::NegativeInt { bigint } => write!(f, "{bigint}")?,
+            Key::PositiveInt { ref bigint } => write!(f, "{bigint}")?,
+            Key::NegativeInt { ref bigint } => write!(f, "{bigint}")?,
             Key::UIntType { bit_width } => write!(f, "u{bit_width}")?,
             Key::SIntType { bit_width } => write!(f, "i{bit_width}")?,
             Key::SimpleType { ty } => write!(f, "{ty}")?,
@@ -207,24 +187,31 @@ impl Display for KeyDisplay<'_> {
             )?,
             Key::FunctionType {
                 return_type,
-                parameters,
-            } => write!(
-                f,
-                "fn ({}) -> {}",
-                DisplayCommaSep {
-                    t: parameters.iter().map(|&ty| self.ip.display_key(ty))
-                },
-                self.ip.display_key(return_type)
-            )?,
+                ref parameters,
+            } => {
+                write!(f, "fn (")?;
+
+                let mut iter =
+                    parameters.iter().map(|&ty| self.ip.display_key(ty));
+                let Some(next) = iter.next() else {
+                    return Ok(());
+                };
+                write!(f, "{next}")?;
+
+                for item in iter {
+                    write!(f, ", {item}")?;
+                }
+                write!(f, ") -> {}", self.ip.display_key(return_type))?;
+            }
             Key::StructType {
                 decl,
                 name,
                 packed,
                 c_like,
-                fields,
+                ref fields,
             } => todo!(),
-            Key::TrueValue => write!(f, "true"),
-            Key::FalseValue => write!(f, "false"),
+            Key::TrueValue => write!(f, "true")?,
+            Key::FalseValue => write!(f, "false")?,
         }
 
         Ok(())
@@ -803,10 +790,60 @@ impl InternPool {
         }
     }
 
-    pub fn from_ast1_type(
+    pub fn insert_ast1_type(
         &mut self,
         pointer_bits: u16,
         ty: &crate::ast::Type,
+    ) -> Index {
+        match ty {
+            crate::ast::Type::Bool => self.get_bool_type(),
+            crate::ast::Type::ComptimeNumber => self.get_comptime_int_type(),
+            crate::ast::Type::Integer(i) => self.get_or_insert({
+                if i.signed {
+                    Key::SIntType { bit_width: i.bits }
+                } else {
+                    Key::UIntType { bit_width: i.bits }
+                }
+            }),
+            crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => {
+                self.get_f32_type()
+            }
+            crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => {
+                self.get_f64_type()
+            }
+            crate::ast::Type::Pointer { constness, pointee } => {
+                let pointee = self.insert_ast1_type(pointer_bits, &pointee);
+                self.get_or_insert(Key::PointerType {
+                    pointee,
+                    flags: PointerFlags::new(*constness, false, false),
+                })
+            }
+            crate::ast::Type::Fn {
+                parameter_types,
+                return_type,
+            } => {
+                let parameters = parameter_types
+                    .iter()
+                    .map(|ty| self.insert_ast1_type(pointer_bits, ty))
+                    .collect::<Vec<_>>();
+                let return_type =
+                    self.from_ast1_type(pointer_bits, &return_type);
+                self.get_or_insert(Key::FunctionType {
+                    return_type,
+                    parameters,
+                })
+            }
+            crate::ast::Type::Void => self.get_void_type(),
+            _ => {
+                todo!()
+            }
+        }
+    }
+
+    pub fn from_ast1_type(
+        &self,
+        pointer_bits: u16,
+        ty: &crate::ast::Type,
     ) -> Index {
         match ty {
             crate::ast::Type::Bool => self.get_bool_type(),
@@ -826,7 +863,7 @@ impl InternPool {
             }
             crate::ast::Type::Pointer { constness, pointee } => {
                 let pointee = self.from_ast1_type(pointer_bits, &pointee);
-                self.get_or_insert(Key::PointerType {
+                self.get_assume_present(&Key::PointerType {
                     pointee,
                     flags: PointerFlags::new(*constness, false, false),
                 })
@@ -841,7 +878,10 @@ impl InternPool {
                     .collect::<Vec<_>>();
                 let return_type =
                     self.from_ast1_type(pointer_bits, &return_type);
-                self.get_function_type(return_type, parameters)
+                self.get_assume_present(&Key::FunctionType {
+                    return_type,
+                    parameters,
+                })
             }
             crate::ast::Type::Void => self.get_void_type(),
             _ => {
@@ -1479,3 +1519,21 @@ impl InternPool {
         })
     }
 }
+
+impl InternPool {
+    pub fn is_function(&self, index: Index) -> bool {
+        matches!(self.get_key(index), Key::FunctionType { .. })
+    }
+    pub fn is_type(&self, index: Index) -> bool {
+        matches!(
+            self.get_key(index),
+            Key::FunctionType { .. }
+                | Key::ArrayType { .. }
+                | Key::PointerType { .. }
+                | Key::SimpleType { .. }
+                | Key::SIntType { .. }
+                | Key::UIntType { .. }
+                | Key::StructType { .. }
+        )
+    }
+}