rukalang/elab/
elaborate_struct_lits.rs

1use super::helpers::canonical_nominal_name;
2use super::prelude::*;
3use crate::syntax::ast::NamedExprField;
4
5impl Elaborator {
6    /// Elaborate one struct literal expression and return its resulting type.
7    pub(super) fn elaborate_struct_lit_expr(
8        &mut self,
9        name: &mut String,
10        fields: &mut [NamedExprField],
11        expected: Option<&Ty>,
12        locals: &mut Vec<(String, Ty)>,
13    ) -> Result<Ty, ElabError> {
14        let template = self
15            .templates
16            .get(name)
17            .cloned()
18            .ok_or_else(|| ElabError::UnknownTypeConstructor { name: name.clone() })?;
19        let mut provided = BTreeMap::new();
20        for field in fields.iter() {
21            if provided.insert(field.name.clone(), ()).is_some() {
22                return Err(ElabError::DuplicateStructLiteralField {
23                    name: name.clone(),
24                    field: field.name.clone(),
25                });
26            }
27        }
28
29        let mut bindings = BTreeMap::new();
30        if let Some(Ty::Struct {
31            name: expected_name,
32            args,
33        }) = expected
34            && expected_name == name
35            && args.len() == template.type_params.len()
36        {
37            for (param, arg) in template.type_params.iter().zip(args.iter()) {
38                bindings.insert(param.clone(), arg.clone());
39            }
40        }
41
42        let type_params = template
43            .type_params
44            .iter()
45            .cloned()
46            .collect::<BTreeSet<_>>();
47        for field in &template.fields {
48            let field_expr = fields
49                .iter_mut()
50                .find(|item| item.name == field.name)
51                .ok_or_else(|| ElabError::MissingStructField {
52                    name: name.clone(),
53                    field: field.name.clone(),
54                })?;
55            let expected_field_ty = self
56                .resolve_type_expr(&field.ty, &bindings, &type_params, None)
57                .ok();
58            let actual_field_ty =
59                self.elaborate_expr(&mut field_expr.value, expected_field_ty.as_ref(), locals)?;
60            self.unify_struct_type_param_bindings(
61                &field.ty,
62                &actual_field_ty,
63                &type_params,
64                &mut bindings,
65            )?;
66        }
67
68        let mut args = Vec::with_capacity(template.type_params.len());
69        for param in &template.type_params {
70            args.push(
71                bindings
72                    .get(param)
73                    .cloned()
74                    .ok_or_else(|| ElabError::StructTypeArgsNotInferred { name: name.clone() })?,
75            );
76        }
77
78        let struct_ty = Ty::Struct {
79            name: name.clone(),
80            args,
81        };
82        self.ensure_ty_instantiated(&struct_ty)?;
83        *name = canonical_nominal_name(&struct_ty);
84        Ok(struct_ty)
85    }
86}