···326326327327 Ok(Spanned::new(
328328 ExprKind::Allocation {
329329- kind: AllocKind::Tuple,
329329+ // filled in during typechecking
330330+ kind: AllocKind::Tuple(vec![]),
330331 elements: exprs,
331332 region: None,
332333 },
···729730730731#[cfg(test)]
731732mod tests {
732732- use std::clone;
733733-734733 use super::*;
735735- use crate::{
736736- ast::{Type, UserDefinedType},
737737- ctx::Symbol,
738738- lex,
739739- };
734734+ use crate::{ast::UserDefinedType, ctx::Symbol, lex};
740735741736 fn tokenify(s: &str) -> (Ctx, VecDeque<SpannedToken>) {
742737 let mut ctx = Ctx::new();
···10671062 let ExprKind::Allocation { kind, elements, .. } = &expr.node else {
10681063 panic!("expected allocation")
10691064 };
10701070- assert!(matches!(kind, AllocKind::Tuple));
10651065+ // types have not been resolved since we did not provide them
10661066+ assert_eq!(*kind, AllocKind::Tuple(vec![]));
10711067 assert_eq!(elements.len(), 3);
10721068 }
10731069}
+18-1
frontend/src/typecheck.rs
···106106 // TODO: implement region handling
107107 // regions should be resolved by the time we get here
108108 let region_handle = region.unwrap_or(Region::Local);
109109- Type::synthetic(TypeKind::Alloc(kind.clone(), region_handle))
109109+ let kind = match kind {
110110+ AllocKind::Tuple(tys) => {
111111+ let mut types = Vec::new();
112112+ for elem in elements {
113113+ types.push(elem.resolve_type(ctx).node);
114114+ }
115115+116116+ if tys.len() != 0 && tys.len() != types.len() && *tys != types {
117117+ panic!("expected tuple types to be equal");
118118+ }
119119+120120+ // here we resolve the tuple types if they were not provided by a type hint
121121+ AllocKind::Tuple(types)
122122+ }
123123+ _ => kind.clone(),
124124+ };
125125+126126+ Type::synthetic(TypeKind::Alloc(kind, region_handle))
110127 }
111128 }
112129 }