Skip to main content

geam_core/plan/module/
constant.rs

1mod function;
2mod list;
3
4use super::{
5    BitArrayBitsSize, BitArrayExpr, BitArrayFunctionExpr, BitArrayListExpr, BitArrayListItem,
6    BitArraySegment, BoolExpr, BoolFunctionExpr, BoolListExpr, BoolListItem, CustomConstruction,
7    CustomConstructor, CustomExpr, CustomFunctionExpr, CustomListExpr, CustomListItem, Expr,
8    ExternalFunctionExpr, ExternalListExpr, ExternalListItem, FloatExpr, FloatFunctionExpr,
9    FloatListExpr, FloatListItem, FunctionExpr, FunctionFunctionExpr, FunctionListExpr,
10    FunctionListItem, FunctionReference, GenericFunctionExpr, GenericListExpr, GenericListItem,
11    IntExpr, IntFunctionExpr, IntListExpr, IntListItem, ListExpr, ListFunctionExpr, ListListExpr,
12    ListListItem, NilExpr, NilFunctionExpr, NilListExpr, NilListItem, ParameterListListExpr,
13    ParameterListListItem, StoredListExpr, StringExpr, StringFunctionExpr, StringListExpr,
14    StringListItem, TupleExpr, TupleFunctionExpr, TupleListExpr, TupleListItem, TypeScheme,
15    TypeSubstitution, TypedFunctionReference, UtfCodepointFunctionExpr, UtfCodepointListExpr,
16    UtfCodepointListItem,
17};
18use crate::plan::{
19    CustomValueShape, Endianness, ExternalValueShape, FloatBitSize, FunctionShape, PanicSite,
20    StringEncoding, ValueShape, ValueType,
21};
22use ecow::EcoString;
23use num_bigint::BigInt;
24
25pub(crate) use function::{
26    ConstantBitArrayFunctionInstantiation, ConstantBoolFunctionInstantiation,
27    ConstantCustomFunctionInstantiation, ConstantExternalFunctionInstantiation,
28    ConstantFloatFunctionInstantiation, ConstantFunctionFunctionInstantiation,
29    ConstantFunctionInstantiation, ConstantFunctionTemplateSource,
30    ConstantGenericFunctionInstantiation, ConstantIntFunctionInstantiation,
31    ConstantListFunctionInstantiation, ConstantNilFunctionInstantiation,
32    ConstantStringFunctionInstantiation, ConstantTupleFunctionInstantiation,
33    ConstantUtfCodepointFunctionInstantiation,
34};
35use function::{
36    ConstantBitArrayFunctionTemplateId, ConstantBitArrayFunctionValue,
37    ConstantBoolFunctionTemplateId, ConstantBoolFunctionValue, ConstantCustomFunctionTarget,
38    ConstantCustomFunctionTemplateId, ConstantCustomFunctionValue,
39    ConstantExternalFunctionTemplateId, ConstantExternalFunctionValue,
40    ConstantFloatFunctionTemplateId, ConstantFloatFunctionValue,
41    ConstantFunctionFunctionTemplateId, ConstantFunctionFunctionValue, ConstantFunctionTemplate,
42    ConstantFunctionValue, ConstantGenericFunctionTemplateId, ConstantGenericFunctionValue,
43    ConstantIntFunctionTemplateId, ConstantIntFunctionValue, ConstantListFunctionTemplateId,
44    ConstantListFunctionValue, ConstantNilFunctionTemplateId, ConstantNilFunctionValue,
45    ConstantStringFunctionTemplateId, ConstantStringFunctionValue, ConstantTupleFunctionTemplateId,
46    ConstantTupleFunctionValue, ConstantUtfCodepointFunctionTemplateId,
47    ConstantUtfCodepointFunctionValue, TypedConstantFunctionValueKind,
48};
49
50pub(crate) use list::{
51    ConstantBitArrayListInstantiation, ConstantBitArrayListTemplateId,
52    ConstantBoolListInstantiation, ConstantBoolListTemplateId, ConstantCustomListInstantiation,
53    ConstantCustomListTemplateId, ConstantExternalListInstantiation,
54    ConstantExternalListTemplateId, ConstantFloatListInstantiation, ConstantFloatListTemplateId,
55    ConstantFunctionListInstantiation, ConstantFunctionListTemplateId,
56    ConstantGenericListInstantiation, ConstantGenericListTemplateId, ConstantIntListInstantiation,
57    ConstantIntListTemplateId, ConstantListInstantiation, ConstantListListInstantiation,
58    ConstantListListTemplateId, ConstantListTemplateSource, ConstantNestedListTemplateSource,
59    ConstantNilListInstantiation, ConstantNilListTemplateId,
60    ConstantParameterListListInstantiation, ConstantParameterListListTemplateId,
61    ConstantStringListInstantiation, ConstantStringListTemplateId, ConstantTupleListInstantiation,
62    ConstantTupleListTemplateId, ConstantUtfCodepointListInstantiation,
63    ConstantUtfCodepointListTemplateId,
64};
65use list::{
66    ConstantBitArrayListValue, ConstantBoolListValue, ConstantCustomListValue,
67    ConstantExternalListValue, ConstantExternalListValueKind, ConstantFloatListValue,
68    ConstantFunctionListValue, ConstantGenericListValue, ConstantGenericListValueKind,
69    ConstantIntListValue, ConstantListListValue, ConstantListParts, ConstantListTemplate,
70    ConstantListValue, ConstantNilListValue, ConstantParameterListListValue,
71    ConstantStoredListValue, ConstantStringListValue, ConstantTupleListValue,
72    ConstantUtfCodepointListValue, ConstantUtfCodepointListValueKind, TypedConstantListValueKind,
73};
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
76pub struct ConstantTemplateId {
77    module: crate::plan::ModuleId,
78    index: usize,
79}
80
81#[derive(Debug, Clone, PartialEq)]
82pub struct ConstantTemplate {
83    signature: ConstantTemplateSignature,
84    name: EcoString,
85}
86
87#[derive(Debug, Clone, PartialEq)]
88pub(crate) struct ConstantTemplates {
89    module: crate::plan::ModuleId,
90    headers: Vec<ConstantTemplate>,
91    generic_lists: Vec<ConstantGenericListValue>,
92    ints: Vec<ConstantIntValue>,
93    strings: Vec<ConstantStringValue>,
94    bit_arrays: Vec<ConstantBitArrayValue>,
95    custom_values: Vec<ConstantCustomValue>,
96    floats: Vec<ConstantFloatValue>,
97    bools: Vec<ConstantBoolValue>,
98    nils: Vec<ConstantNilValue>,
99    tuples: Vec<ConstantTupleValue>,
100    int_lists: Vec<ConstantIntListValue>,
101    string_lists: Vec<ConstantStringListValue>,
102    bit_array_lists: Vec<ConstantBitArrayListValue>,
103    utf_codepoint_lists: Vec<ConstantUtfCodepointListValue>,
104    custom_lists: Vec<ConstantCustomListValue>,
105    external_lists: Vec<ConstantExternalListValue>,
106    float_lists: Vec<ConstantFloatListValue>,
107    bool_lists: Vec<ConstantBoolListValue>,
108    nil_lists: Vec<ConstantNilListValue>,
109    tuple_lists: Vec<ConstantTupleListValue>,
110    parameter_list_lists: Vec<ConstantParameterListListValue>,
111    list_lists: Vec<ConstantListListValue>,
112    function_lists: Vec<ConstantFunctionListValue>,
113    generic_functions: Vec<ConstantGenericFunctionValue>,
114    int_functions: Vec<ConstantIntFunctionValue>,
115    string_functions: Vec<ConstantStringFunctionValue>,
116    bit_array_functions: Vec<ConstantBitArrayFunctionValue>,
117    utf_codepoint_functions: Vec<ConstantUtfCodepointFunctionValue>,
118    custom_functions: Vec<ConstantCustomFunctionValue>,
119    external_functions: Vec<ConstantExternalFunctionValue>,
120    float_functions: Vec<ConstantFloatFunctionValue>,
121    bool_functions: Vec<ConstantBoolFunctionValue>,
122    nil_functions: Vec<ConstantNilFunctionValue>,
123    tuple_functions: Vec<ConstantTupleFunctionValue>,
124    list_functions: Vec<ConstantListFunctionValue>,
125    function_functions: Vec<ConstantFunctionFunctionValue>,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq)]
129pub(crate) struct ConstantTemplateSignature {
130    id: ConstantTemplateId,
131    scheme: TypeScheme,
132    shape: ValueShape,
133    kind: ConstantTemplateSignatureKind,
134}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
137enum ConstantTemplateSignatureKind {
138    Int(ConstantIntTemplateId),
139    String(ConstantStringTemplateId),
140    BitArray(ConstantBitArrayTemplateId),
141    Custom {
142        template: ConstantCustomTemplateId,
143        shape: CustomValueShape,
144    },
145    Float(ConstantFloatTemplateId),
146    Bool(ConstantBoolTemplateId),
147    Nil(ConstantNilTemplateId),
148    Tuple {
149        template: ConstantTupleTemplateId,
150        shape: Box<[ValueShape]>,
151    },
152    List(ConstantListTemplate),
153    Function {
154        template: ConstantFunctionTemplate,
155        shape: FunctionShape,
156    },
157}
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
160pub(crate) struct ConstantIntTemplateId(pub(crate) usize);
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
163pub(crate) struct ConstantStringTemplateId(pub(crate) usize);
164
165#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
166pub(crate) struct ConstantBitArrayTemplateId(pub(crate) usize);
167
168#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
169pub(crate) struct ConstantCustomTemplateId(pub(crate) usize);
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
172pub(crate) struct ConstantFloatTemplateId(pub(crate) usize);
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
175pub(crate) struct ConstantBoolTemplateId(pub(crate) usize);
176
177#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
178pub(crate) struct ConstantNilTemplateId(pub(crate) usize);
179
180#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
181pub(crate) struct ConstantTupleTemplateId(pub(crate) usize);
182
183#[derive(Debug, Clone, PartialEq, Eq, Hash)]
184pub(crate) struct TypedConstantInstantiation<Id, Shape> {
185    module: crate::plan::ModuleId,
186    template: Id,
187    substitution: TypeSubstitution,
188    shape: Shape,
189}
190
191pub(crate) type ConstantIntInstantiation = TypedConstantInstantiation<ConstantIntTemplateId, ()>;
192pub(crate) type ConstantStringInstantiation =
193    TypedConstantInstantiation<ConstantStringTemplateId, ()>;
194pub(crate) type ConstantBitArrayInstantiation =
195    TypedConstantInstantiation<ConstantBitArrayTemplateId, ()>;
196pub(crate) type ConstantCustomInstantiation =
197    TypedConstantInstantiation<ConstantCustomTemplateId, CustomValueShape>;
198pub(crate) type ConstantFloatInstantiation =
199    TypedConstantInstantiation<ConstantFloatTemplateId, ()>;
200pub(crate) type ConstantBoolInstantiation = TypedConstantInstantiation<ConstantBoolTemplateId, ()>;
201pub(crate) type ConstantNilInstantiation = TypedConstantInstantiation<ConstantNilTemplateId, ()>;
202pub(crate) type ConstantTupleInstantiation =
203    TypedConstantInstantiation<ConstantTupleTemplateId, Box<[ValueShape]>>;
204
205#[derive(Debug, Clone, PartialEq, Eq, Hash)]
206pub(crate) struct ConstantInstantiation {
207    kind: ConstantInstantiationKind,
208}
209
210#[derive(Debug, Clone, PartialEq, Eq, Hash)]
211enum ConstantInstantiationKind {
212    Int(ConstantIntInstantiation),
213    String(ConstantStringInstantiation),
214    BitArray(ConstantBitArrayInstantiation),
215    Custom(ConstantCustomInstantiation),
216    Float(ConstantFloatInstantiation),
217    Bool(ConstantBoolInstantiation),
218    Nil(ConstantNilInstantiation),
219    Tuple(ConstantTupleInstantiation),
220    List(ConstantListInstantiation),
221    Function(ConstantFunctionInstantiation),
222}
223
224#[derive(Debug, Clone, PartialEq, Eq, Hash)]
225pub(crate) struct ConstantIntReference(ConstantIntInstantiation);
226
227#[derive(Debug, Clone, PartialEq, Eq, Hash)]
228pub(crate) struct ConstantStringReference(ConstantStringInstantiation);
229
230#[derive(Debug, Clone, PartialEq, Eq, Hash)]
231pub(crate) struct ConstantBitArrayReference(ConstantBitArrayInstantiation);
232
233#[derive(Debug, Clone, PartialEq, Eq, Hash)]
234pub(crate) struct ConstantCustomReference(ConstantCustomInstantiation);
235
236#[derive(Debug, Clone, PartialEq, Eq, Hash)]
237pub(crate) struct ConstantFloatReference(ConstantFloatInstantiation);
238
239#[derive(Debug, Clone, PartialEq, Eq, Hash)]
240pub(crate) struct ConstantBoolReference(ConstantBoolInstantiation);
241
242#[derive(Debug, Clone, PartialEq, Eq, Hash)]
243pub(crate) struct ConstantNilReference(ConstantNilInstantiation);
244
245#[derive(Debug, Clone, PartialEq, Eq, Hash)]
246pub(crate) struct ConstantTupleReference(ConstantTupleInstantiation);
247
248impl ConstantCustomReference {
249    pub(crate) fn instantiation(&self) -> &ConstantCustomInstantiation {
250        &self.0
251    }
252
253    pub(crate) fn shape(&self) -> &CustomValueShape {
254        self.0.shape()
255    }
256}
257
258impl ConstantTupleReference {
259    pub(crate) fn instantiation(&self) -> &ConstantTupleInstantiation {
260        &self.0
261    }
262
263    pub(crate) fn shape(&self) -> &[ValueShape] {
264        self.0.shape()
265    }
266}
267
268impl ConstantIntReference {
269    pub(crate) fn instantiation(&self) -> &ConstantIntInstantiation {
270        &self.0
271    }
272}
273
274impl ConstantStringReference {
275    pub(crate) fn instantiation(&self) -> &ConstantStringInstantiation {
276        &self.0
277    }
278}
279
280impl ConstantBitArrayReference {
281    pub(crate) fn instantiation(&self) -> &ConstantBitArrayInstantiation {
282        &self.0
283    }
284}
285
286impl ConstantFloatReference {
287    pub(crate) fn instantiation(&self) -> &ConstantFloatInstantiation {
288        &self.0
289    }
290}
291
292impl ConstantBoolReference {
293    pub(crate) fn instantiation(&self) -> &ConstantBoolInstantiation {
294        &self.0
295    }
296}
297
298impl ConstantNilReference {
299    pub(crate) fn instantiation(&self) -> &ConstantNilInstantiation {
300        &self.0
301    }
302}
303
304impl ConstantInstantiation {
305    pub(crate) fn from_int(value: ConstantIntInstantiation) -> Self {
306        Self {
307            kind: ConstantInstantiationKind::Int(value),
308        }
309    }
310
311    pub(crate) fn from_string(value: ConstantStringInstantiation) -> Self {
312        Self {
313            kind: ConstantInstantiationKind::String(value),
314        }
315    }
316
317    pub(crate) fn from_bit_array(value: ConstantBitArrayInstantiation) -> Self {
318        Self {
319            kind: ConstantInstantiationKind::BitArray(value),
320        }
321    }
322
323    pub(crate) fn from_custom(value: ConstantCustomInstantiation) -> Self {
324        Self {
325            kind: ConstantInstantiationKind::Custom(value),
326        }
327    }
328
329    pub(crate) fn from_float(value: ConstantFloatInstantiation) -> Self {
330        Self {
331            kind: ConstantInstantiationKind::Float(value),
332        }
333    }
334
335    pub(crate) fn from_bool(value: ConstantBoolInstantiation) -> Self {
336        Self {
337            kind: ConstantInstantiationKind::Bool(value),
338        }
339    }
340
341    pub(crate) fn from_nil(value: ConstantNilInstantiation) -> Self {
342        Self {
343            kind: ConstantInstantiationKind::Nil(value),
344        }
345    }
346
347    pub(crate) fn from_tuple(value: ConstantTupleInstantiation) -> Self {
348        Self {
349            kind: ConstantInstantiationKind::Tuple(value),
350        }
351    }
352
353    pub(crate) fn from_list(value: ConstantListInstantiation) -> Self {
354        Self {
355            kind: ConstantInstantiationKind::List(value),
356        }
357    }
358
359    pub(crate) fn from_function(value: ConstantFunctionInstantiation) -> Self {
360        Self {
361            kind: ConstantInstantiationKind::Function(value),
362        }
363    }
364
365    pub(crate) fn module(&self) -> crate::plan::ModuleId {
366        match &self.kind {
367            ConstantInstantiationKind::Int(value) => value.module(),
368            ConstantInstantiationKind::String(value) => value.module(),
369            ConstantInstantiationKind::BitArray(value) => value.module(),
370            ConstantInstantiationKind::Custom(value) => value.module(),
371            ConstantInstantiationKind::Float(value) => value.module(),
372            ConstantInstantiationKind::Bool(value) => value.module(),
373            ConstantInstantiationKind::Nil(value) => value.module(),
374            ConstantInstantiationKind::Tuple(value) => value.module(),
375            ConstantInstantiationKind::List(value) => value.module(),
376            ConstantInstantiationKind::Function(value) => value.module(),
377        }
378    }
379
380    pub(crate) fn substitute(&self, outer: &TypeSubstitution) -> Self {
381        let kind = match &self.kind {
382            ConstantInstantiationKind::Int(value) => {
383                ConstantInstantiationKind::Int(value.substitute_leaf(outer))
384            }
385            ConstantInstantiationKind::String(value) => {
386                ConstantInstantiationKind::String(value.substitute_leaf(outer))
387            }
388            ConstantInstantiationKind::BitArray(value) => {
389                ConstantInstantiationKind::BitArray(value.substitute_leaf(outer))
390            }
391            ConstantInstantiationKind::Custom(value) => {
392                ConstantInstantiationKind::Custom(value.substitute_custom(outer))
393            }
394            ConstantInstantiationKind::Float(value) => {
395                ConstantInstantiationKind::Float(value.substitute_leaf(outer))
396            }
397            ConstantInstantiationKind::Bool(value) => {
398                ConstantInstantiationKind::Bool(value.substitute_leaf(outer))
399            }
400            ConstantInstantiationKind::Nil(value) => {
401                ConstantInstantiationKind::Nil(value.substitute_leaf(outer))
402            }
403            ConstantInstantiationKind::Tuple(value) => {
404                ConstantInstantiationKind::Tuple(value.substitute_tuple(outer))
405            }
406            ConstantInstantiationKind::List(value) => {
407                ConstantInstantiationKind::List(value.substitute(outer))
408            }
409            ConstantInstantiationKind::Function(value) => {
410                ConstantInstantiationKind::Function(value.substitute(outer))
411            }
412        };
413        Self { kind }
414    }
415}
416
417#[derive(Debug, Clone, PartialEq)]
418pub(crate) enum ConstantIntValue {
419    Value(BigInt),
420    Reference(ConstantIntInstantiation),
421}
422
423#[derive(Debug, Clone, PartialEq)]
424pub(crate) enum ConstantFloatValue {
425    Value(f64),
426    Reference(ConstantFloatInstantiation),
427}
428
429#[derive(Debug, Clone, PartialEq)]
430pub(crate) enum ConstantStringValue {
431    Value(EcoString),
432    Concatenation {
433        left: Box<ConstantStringValue>,
434        right: Box<ConstantStringValue>,
435    },
436    Reference(ConstantStringInstantiation),
437}
438
439#[derive(Debug, Clone, PartialEq)]
440pub(crate) enum ConstantBoolValue {
441    Value(bool),
442    Reference(ConstantBoolInstantiation),
443}
444
445#[derive(Debug, Clone, PartialEq)]
446pub(crate) enum ConstantNilValue {
447    Value,
448    Reference(ConstantNilInstantiation),
449}
450
451#[derive(Debug, Clone, PartialEq)]
452pub(crate) struct ConstantTupleValue {
453    shape: Box<[ValueShape]>,
454    kind: ConstantTupleValueKind,
455}
456
457#[derive(Debug, Clone, PartialEq)]
458pub(crate) enum ConstantTupleValueKind {
459    Value(Box<[ConstantValue]>),
460    Reference(ConstantTupleInstantiation),
461}
462
463#[derive(Debug, Clone, PartialEq)]
464pub(crate) struct ConstantBitArrayValue {
465    kind: ConstantBitArrayValueKind,
466}
467
468#[derive(Debug, Clone, PartialEq)]
469pub(crate) enum ConstantBitArrayValueKind {
470    Value(Box<[ConstantBitArraySegment]>),
471    Reference(ConstantBitArrayInstantiation),
472}
473
474#[derive(Debug, Clone, PartialEq)]
475pub(crate) struct ConstantCustomValue {
476    shape: CustomValueShape,
477    kind: ConstantCustomValueKind,
478}
479
480#[derive(Debug, Clone, PartialEq)]
481pub(crate) enum ConstantCustomValueKind {
482    Construction(ConstantCustomConstruction),
483    Reference(ConstantCustomInstantiation),
484}
485
486#[derive(Debug, Clone, PartialEq)]
487pub(crate) struct ConstantCustomConstruction {
488    constructor: CustomConstructor,
489    fields: Box<[ConstantValue]>,
490}
491
492#[derive(Debug)]
493pub(crate) struct MaterializedConstantCustomConstruction {
494    constructor: CustomConstructor,
495    fields: Box<[super::Expr]>,
496}
497
498#[derive(Debug, Clone, PartialEq)]
499pub(crate) struct ConstantValue {
500    kind: ConstantValueKind,
501}
502
503#[derive(Debug, Clone, PartialEq)]
504enum ConstantValueKind {
505    Int(ConstantIntValue),
506    Float(ConstantFloatValue),
507    String(ConstantStringValue),
508    Bool(ConstantBoolValue),
509    Nil(ConstantNilValue),
510    Tuple(ConstantTupleValue),
511    List(ConstantListValue),
512    BitArray(ConstantBitArrayValue),
513    Custom(ConstantCustomValue),
514    Function(ConstantFunctionValue),
515}
516
517#[derive(Debug, Clone, PartialEq, Eq)]
518pub(crate) enum ConstantListConstructionError {
519    TypeMismatch {
520        expected: ValueType,
521        actual: ValueType,
522    },
523    SpreadWithoutElements,
524}
525
526#[derive(Debug, Clone, PartialEq)]
527pub(crate) enum ConstantBitArraySegment {
528    Int {
529        value: ConstantIntValue,
530        bit_size: usize,
531        endianness: Endianness,
532    },
533    Float {
534        value: ConstantFloatValue,
535        bit_size: FloatBitSize,
536        endianness: Endianness,
537    },
538    String {
539        value: ConstantStringValue,
540        encoding: StringEncoding,
541    },
542    Bits(ConstantBitArrayValue),
543    SizedBits {
544        value: ConstantBitArrayValue,
545        bit_size: usize,
546        site: PanicSite,
547    },
548}
549
550impl ConstantTemplateId {
551    #[cfg(test)]
552    pub(crate) fn new(index: usize) -> Self {
553        Self::in_module(crate::plan::ModuleId::root(), index)
554    }
555
556    pub(crate) fn in_module(module: crate::plan::ModuleId, index: usize) -> Self {
557        Self { module, index }
558    }
559
560    pub fn module(self) -> crate::plan::ModuleId {
561        self.module
562    }
563
564    pub(crate) fn index(self) -> usize {
565        self.index
566    }
567}
568
569impl ConstantTemplate {
570    pub(crate) fn new(signature: ConstantTemplateSignature, name: EcoString) -> Self {
571        Self { signature, name }
572    }
573
574    pub fn id(&self) -> ConstantTemplateId {
575        self.signature.id()
576    }
577
578    pub fn name(&self) -> &EcoString {
579        &self.name
580    }
581
582    pub fn scheme(&self) -> &TypeScheme {
583        self.signature.scheme()
584    }
585
586    #[cfg(test)]
587    pub(crate) fn signature(&self) -> &ConstantTemplateSignature {
588        &self.signature
589    }
590}
591
592impl ConstantTemplates {
593    pub(crate) fn from_module_entries(
594        module: crate::plan::ModuleId,
595        entries: Vec<(ConstantTemplate, ConstantValue)>,
596    ) -> Self {
597        let mut templates = Self {
598            module,
599            headers: Vec::with_capacity(entries.len()),
600            generic_lists: Vec::new(),
601            ints: Vec::new(),
602            strings: Vec::new(),
603            bit_arrays: Vec::new(),
604            custom_values: Vec::new(),
605            floats: Vec::new(),
606            bools: Vec::new(),
607            nils: Vec::new(),
608            tuples: Vec::new(),
609            int_lists: Vec::new(),
610            string_lists: Vec::new(),
611            bit_array_lists: Vec::new(),
612            utf_codepoint_lists: Vec::new(),
613            custom_lists: Vec::new(),
614            external_lists: Vec::new(),
615            float_lists: Vec::new(),
616            bool_lists: Vec::new(),
617            nil_lists: Vec::new(),
618            tuple_lists: Vec::new(),
619            parameter_list_lists: Vec::new(),
620            list_lists: Vec::new(),
621            function_lists: Vec::new(),
622            generic_functions: Vec::new(),
623            int_functions: Vec::new(),
624            string_functions: Vec::new(),
625            bit_array_functions: Vec::new(),
626            utf_codepoint_functions: Vec::new(),
627            custom_functions: Vec::new(),
628            external_functions: Vec::new(),
629            float_functions: Vec::new(),
630            bool_functions: Vec::new(),
631            nil_functions: Vec::new(),
632            tuple_functions: Vec::new(),
633            list_functions: Vec::new(),
634            function_functions: Vec::new(),
635        };
636        for (template, value) in entries {
637            templates.headers.push(template);
638            templates.push_value(value);
639        }
640        templates
641    }
642
643    fn push_value(&mut self, value: ConstantValue) {
644        match value.kind {
645            ConstantValueKind::Int(value) => self.ints.push(value),
646            ConstantValueKind::Float(value) => self.floats.push(value),
647            ConstantValueKind::String(value) => self.strings.push(value),
648            ConstantValueKind::Bool(value) => self.bools.push(value),
649            ConstantValueKind::Nil(value) => self.nils.push(value),
650            ConstantValueKind::Tuple(value) => self.tuples.push(value),
651            ConstantValueKind::List(value) => match value {
652                ConstantListValue::Generic(value) => self.generic_lists.push(value),
653                ConstantListValue::ParameterList(value) => self.parameter_list_lists.push(value),
654                ConstantListValue::Int(value) => self.int_lists.push(value),
655                ConstantListValue::String(value) => self.string_lists.push(value),
656                ConstantListValue::BitArray(value) => self.bit_array_lists.push(value),
657                ConstantListValue::UtfCodepoint(value) => self.utf_codepoint_lists.push(value),
658                ConstantListValue::Custom(value) => self.custom_lists.push(value),
659                ConstantListValue::External(value) => self.external_lists.push(value),
660                ConstantListValue::Float(value) => self.float_lists.push(value),
661                ConstantListValue::Bool(value) => self.bool_lists.push(value),
662                ConstantListValue::Nil(value) => self.nil_lists.push(value),
663                ConstantListValue::Tuple(value) => self.tuple_lists.push(value),
664                ConstantListValue::List(value) => self.list_lists.push(value),
665                ConstantListValue::Function(value) => self.function_lists.push(value),
666            },
667            ConstantValueKind::BitArray(value) => self.bit_arrays.push(value),
668            ConstantValueKind::Custom(value) => self.custom_values.push(value),
669            ConstantValueKind::Function(value) => match value {
670                ConstantFunctionValue::Generic(value) => self.generic_functions.push(value),
671                ConstantFunctionValue::Int(value) => self.int_functions.push(value),
672                ConstantFunctionValue::String(value) => self.string_functions.push(value),
673                ConstantFunctionValue::BitArray(value) => self.bit_array_functions.push(value),
674                ConstantFunctionValue::UtfCodepoint(value) => {
675                    self.utf_codepoint_functions.push(value)
676                }
677                ConstantFunctionValue::Custom(value) => self.custom_functions.push(value),
678                ConstantFunctionValue::External(value) => self.external_functions.push(value),
679                ConstantFunctionValue::Float(value) => self.float_functions.push(value),
680                ConstantFunctionValue::Bool(value) => self.bool_functions.push(value),
681                ConstantFunctionValue::Nil(value) => self.nil_functions.push(value),
682                ConstantFunctionValue::Tuple(value) => self.tuple_functions.push(value),
683                ConstantFunctionValue::List(value) => self.list_functions.push(value),
684                ConstantFunctionValue::Function(value) => self.function_functions.push(value),
685            },
686        }
687    }
688
689    #[cfg(test)]
690    pub(crate) fn from_entries(entries: Vec<(ConstantTemplate, ConstantValue)>) -> Self {
691        Self::from_module_entries(crate::plan::ModuleId::root(), entries)
692    }
693
694    #[cfg(test)]
695    pub(crate) fn empty() -> Self {
696        Self::from_entries(Vec::new())
697    }
698
699    fn owns(&self, module: crate::plan::ModuleId) -> bool {
700        self.module == module
701    }
702
703    pub(crate) fn headers(&self) -> &[ConstantTemplate] {
704        &self.headers
705    }
706
707    #[cfg(test)]
708    pub(crate) fn header(&self, id: ConstantTemplateId) -> &ConstantTemplate {
709        &self.headers[id.index()]
710    }
711
712    pub(crate) fn int(&self, id: ConstantIntTemplateId) -> &ConstantIntValue {
713        &self.ints[id.0]
714    }
715
716    pub(crate) fn string(&self, id: ConstantStringTemplateId) -> &ConstantStringValue {
717        &self.strings[id.0]
718    }
719
720    pub(crate) fn bit_array(&self, id: ConstantBitArrayTemplateId) -> &ConstantBitArrayValue {
721        &self.bit_arrays[id.0]
722    }
723
724    pub(crate) fn custom(&self, id: ConstantCustomTemplateId) -> &ConstantCustomValue {
725        &self.custom_values[id.0]
726    }
727
728    pub(crate) fn float(&self, id: ConstantFloatTemplateId) -> &ConstantFloatValue {
729        &self.floats[id.0]
730    }
731
732    pub(crate) fn bool(&self, id: ConstantBoolTemplateId) -> &ConstantBoolValue {
733        &self.bools[id.0]
734    }
735
736    pub(crate) fn nil(&self, id: ConstantNilTemplateId) -> &ConstantNilValue {
737        &self.nils[id.0]
738    }
739
740    pub(crate) fn tuple(&self, id: ConstantTupleTemplateId) -> &ConstantTupleValue {
741        &self.tuples[id.0]
742    }
743
744    fn generic_list(&self, id: ConstantGenericListTemplateId) -> &ConstantGenericListValue {
745        &self.generic_lists[id.0]
746    }
747
748    fn int_list(&self, id: ConstantIntListTemplateId) -> &ConstantIntListValue {
749        &self.int_lists[id.0]
750    }
751
752    fn string_list(&self, id: ConstantStringListTemplateId) -> &ConstantStringListValue {
753        &self.string_lists[id.0]
754    }
755
756    fn bit_array_list(&self, id: ConstantBitArrayListTemplateId) -> &ConstantBitArrayListValue {
757        &self.bit_array_lists[id.0]
758    }
759
760    fn utf_codepoint_list(
761        &self,
762        id: ConstantUtfCodepointListTemplateId,
763    ) -> &ConstantUtfCodepointListValue {
764        &self.utf_codepoint_lists[id.0]
765    }
766
767    fn custom_list(&self, id: ConstantCustomListTemplateId) -> &ConstantCustomListValue {
768        &self.custom_lists[id.0]
769    }
770
771    fn external_list(&self, id: ConstantExternalListTemplateId) -> &ConstantExternalListValue {
772        &self.external_lists[id.0]
773    }
774
775    fn float_list(&self, id: ConstantFloatListTemplateId) -> &ConstantFloatListValue {
776        &self.float_lists[id.0]
777    }
778
779    fn bool_list(&self, id: ConstantBoolListTemplateId) -> &ConstantBoolListValue {
780        &self.bool_lists[id.0]
781    }
782
783    fn nil_list(&self, id: ConstantNilListTemplateId) -> &ConstantNilListValue {
784        &self.nil_lists[id.0]
785    }
786
787    fn tuple_list(&self, id: ConstantTupleListTemplateId) -> &ConstantTupleListValue {
788        &self.tuple_lists[id.0]
789    }
790
791    fn list_list(&self, id: ConstantListListTemplateId) -> &ConstantListListValue {
792        &self.list_lists[id.0]
793    }
794
795    fn parameter_list_list(
796        &self,
797        id: ConstantParameterListListTemplateId,
798    ) -> &ConstantParameterListListValue {
799        &self.parameter_list_lists[id.0]
800    }
801
802    fn function_list(&self, id: ConstantFunctionListTemplateId) -> &ConstantFunctionListValue {
803        &self.function_lists[id.0]
804    }
805
806    fn generic_function(
807        &self,
808        id: ConstantGenericFunctionTemplateId,
809    ) -> &ConstantGenericFunctionValue {
810        &self.generic_functions[id.0]
811    }
812
813    fn int_function(&self, id: ConstantIntFunctionTemplateId) -> &ConstantIntFunctionValue {
814        &self.int_functions[id.0]
815    }
816
817    fn string_function(
818        &self,
819        id: ConstantStringFunctionTemplateId,
820    ) -> &ConstantStringFunctionValue {
821        &self.string_functions[id.0]
822    }
823
824    fn bit_array_function(
825        &self,
826        id: ConstantBitArrayFunctionTemplateId,
827    ) -> &ConstantBitArrayFunctionValue {
828        &self.bit_array_functions[id.0]
829    }
830
831    fn utf_codepoint_function(
832        &self,
833        id: ConstantUtfCodepointFunctionTemplateId,
834    ) -> &ConstantUtfCodepointFunctionValue {
835        &self.utf_codepoint_functions[id.0]
836    }
837
838    fn custom_function(
839        &self,
840        id: ConstantCustomFunctionTemplateId,
841    ) -> &ConstantCustomFunctionValue {
842        &self.custom_functions[id.0]
843    }
844
845    fn external_function(
846        &self,
847        id: ConstantExternalFunctionTemplateId,
848    ) -> &ConstantExternalFunctionValue {
849        &self.external_functions[id.0]
850    }
851
852    fn float_function(&self, id: ConstantFloatFunctionTemplateId) -> &ConstantFloatFunctionValue {
853        &self.float_functions[id.0]
854    }
855
856    fn bool_function(&self, id: ConstantBoolFunctionTemplateId) -> &ConstantBoolFunctionValue {
857        &self.bool_functions[id.0]
858    }
859
860    fn nil_function(&self, id: ConstantNilFunctionTemplateId) -> &ConstantNilFunctionValue {
861        &self.nil_functions[id.0]
862    }
863
864    fn tuple_function(&self, id: ConstantTupleFunctionTemplateId) -> &ConstantTupleFunctionValue {
865        &self.tuple_functions[id.0]
866    }
867
868    fn list_function(&self, id: ConstantListFunctionTemplateId) -> &ConstantListFunctionValue {
869        &self.list_functions[id.0]
870    }
871
872    fn function_function(
873        &self,
874        id: ConstantFunctionFunctionTemplateId,
875    ) -> &ConstantFunctionFunctionValue {
876        &self.function_functions[id.0]
877    }
878
879    pub(crate) fn reference(instantiation: ConstantInstantiation) -> Expr {
880        match instantiation.kind {
881            ConstantInstantiationKind::Int(value) => {
882                Expr::int(IntExpr::constant(ConstantIntReference(value)))
883            }
884            ConstantInstantiationKind::String(value) => {
885                Expr::string(StringExpr::constant(ConstantStringReference(value)))
886            }
887            ConstantInstantiationKind::BitArray(value) => {
888                Expr::bit_array(BitArrayExpr::constant(ConstantBitArrayReference(value)))
889            }
890            ConstantInstantiationKind::Custom(value) => {
891                Expr::custom(CustomExpr::constant(ConstantCustomReference(value)))
892            }
893            ConstantInstantiationKind::Float(value) => {
894                Expr::float(FloatExpr::constant(ConstantFloatReference(value)))
895            }
896            ConstantInstantiationKind::Bool(value) => {
897                Expr::bool(BoolExpr::constant(ConstantBoolReference(value)))
898            }
899            ConstantInstantiationKind::Nil(value) => {
900                Expr::nil(NilExpr::constant(ConstantNilReference(value)))
901            }
902            ConstantInstantiationKind::Tuple(value) => {
903                Expr::tuple(TupleExpr::constant(ConstantTupleReference(value)))
904            }
905            ConstantInstantiationKind::List(value) => Expr::list(ListExpr::constant(value)),
906            ConstantInstantiationKind::Function(value) => {
907                Expr::function(FunctionExpr::constant(value.clone()))
908            }
909        }
910    }
911
912    fn materialize_value(&self, value: &ConstantValue, substitution: &TypeSubstitution) -> Expr {
913        match &value.kind {
914            ConstantValueKind::Int(value) => {
915                Expr::int(self.materialize_int_value(value, substitution))
916            }
917            ConstantValueKind::Float(value) => {
918                Expr::float(self.materialize_float_value(value, substitution))
919            }
920            ConstantValueKind::String(value) => {
921                Expr::string(self.materialize_string_value(value, substitution))
922            }
923            ConstantValueKind::Bool(value) => {
924                Expr::bool(self.materialize_bool_value(value, substitution))
925            }
926            ConstantValueKind::Nil(value) => {
927                Expr::nil(self.materialize_nil_value(value, substitution))
928            }
929            ConstantValueKind::Tuple(value) => {
930                Expr::tuple(self.materialize_tuple_value(value, substitution))
931            }
932            ConstantValueKind::List(value) => {
933                Expr::list(self.materialize_list_value(value, substitution))
934            }
935            ConstantValueKind::BitArray(value) => {
936                Expr::bit_array(self.materialize_bit_array_value(value, substitution))
937            }
938            ConstantValueKind::Custom(value) => {
939                Expr::custom(self.materialize_custom_value(value, substitution))
940            }
941            ConstantValueKind::Function(value) => {
942                Expr::function(self.materialize_function_value(value, substitution))
943            }
944        }
945    }
946
947    pub(crate) fn materialize_int(&self, value: &ConstantIntInstantiation) -> IntExpr {
948        if !self.owns(value.module()) {
949            return IntExpr::constant(ConstantIntReference(value.clone()));
950        }
951        self.materialize_int_value(self.int(value.template()), value.substitution())
952    }
953
954    fn materialize_int_value(
955        &self,
956        value: &ConstantIntValue,
957        substitution: &TypeSubstitution,
958    ) -> IntExpr {
959        match value {
960            ConstantIntValue::Value(value) => IntExpr::value(value.clone()),
961            ConstantIntValue::Reference(value) => {
962                self.materialize_int(&value.substitute_leaf(substitution))
963            }
964        }
965    }
966
967    pub(crate) fn materialize_float(&self, value: &ConstantFloatInstantiation) -> FloatExpr {
968        if !self.owns(value.module()) {
969            return FloatExpr::constant(ConstantFloatReference(value.clone()));
970        }
971        self.materialize_float_value(self.float(value.template()), value.substitution())
972    }
973
974    fn materialize_float_value(
975        &self,
976        value: &ConstantFloatValue,
977        substitution: &TypeSubstitution,
978    ) -> FloatExpr {
979        match value {
980            ConstantFloatValue::Value(value) => FloatExpr::value(*value),
981            ConstantFloatValue::Reference(value) => {
982                self.materialize_float(&value.substitute_leaf(substitution))
983            }
984        }
985    }
986
987    pub(crate) fn materialize_string(&self, value: &ConstantStringInstantiation) -> StringExpr {
988        if !self.owns(value.module()) {
989            return StringExpr::constant(ConstantStringReference(value.clone()));
990        }
991        self.materialize_string_value(self.string(value.template()), value.substitution())
992    }
993
994    fn materialize_string_value(
995        &self,
996        value: &ConstantStringValue,
997        substitution: &TypeSubstitution,
998    ) -> StringExpr {
999        match value {
1000            ConstantStringValue::Value(value) => StringExpr::value(value.clone()),
1001            ConstantStringValue::Concatenation { left, right } => StringExpr::concatenate(
1002                self.materialize_string_value(left, substitution),
1003                self.materialize_string_value(right, substitution),
1004            ),
1005            ConstantStringValue::Reference(value) => {
1006                self.materialize_string(&value.substitute_leaf(substitution))
1007            }
1008        }
1009    }
1010
1011    pub(crate) fn materialize_bool(&self, value: &ConstantBoolInstantiation) -> BoolExpr {
1012        if !self.owns(value.module()) {
1013            return BoolExpr::constant(ConstantBoolReference(value.clone()));
1014        }
1015        self.materialize_bool_value(self.bool(value.template()), value.substitution())
1016    }
1017
1018    fn materialize_bool_value(
1019        &self,
1020        value: &ConstantBoolValue,
1021        substitution: &TypeSubstitution,
1022    ) -> BoolExpr {
1023        match value {
1024            ConstantBoolValue::Value(value) => BoolExpr::value(*value),
1025            ConstantBoolValue::Reference(value) => {
1026                self.materialize_bool(&value.substitute_leaf(substitution))
1027            }
1028        }
1029    }
1030
1031    pub(crate) fn materialize_nil(&self, value: &ConstantNilInstantiation) -> NilExpr {
1032        if !self.owns(value.module()) {
1033            return NilExpr::constant(ConstantNilReference(value.clone()));
1034        }
1035        self.materialize_nil_value(self.nil(value.template()), value.substitution())
1036    }
1037
1038    fn materialize_nil_value(
1039        &self,
1040        value: &ConstantNilValue,
1041        substitution: &TypeSubstitution,
1042    ) -> NilExpr {
1043        match value {
1044            ConstantNilValue::Value => NilExpr::value(),
1045            ConstantNilValue::Reference(value) => {
1046                self.materialize_nil(&value.substitute_leaf(substitution))
1047            }
1048        }
1049    }
1050
1051    pub(crate) fn materialize_tuple(&self, value: &ConstantTupleInstantiation) -> TupleExpr {
1052        if !self.owns(value.module()) {
1053            return TupleExpr::constant(ConstantTupleReference(value.clone()));
1054        }
1055        self.materialize_tuple_value(self.tuple(value.template()), value.substitution())
1056    }
1057
1058    fn materialize_tuple_value(
1059        &self,
1060        value: &ConstantTupleValue,
1061        substitution: &TypeSubstitution,
1062    ) -> TupleExpr {
1063        match value.kind() {
1064            ConstantTupleValueKind::Value(elements) => {
1065                let shape = value
1066                    .shape()
1067                    .iter()
1068                    .map(|shape| shape.substitute(substitution))
1069                    .collect::<Vec<_>>()
1070                    .into_boxed_slice();
1071                TupleExpr::value(
1072                    elements
1073                        .iter()
1074                        .map(|element| self.materialize_value(element, substitution))
1075                        .collect(),
1076                    shape.iter().map(ValueShape::value_type).collect(),
1077                )
1078                .with_shape(shape)
1079            }
1080            ConstantTupleValueKind::Reference(value) => {
1081                self.materialize_tuple(&value.substitute_tuple(substitution))
1082            }
1083        }
1084    }
1085
1086    pub(crate) fn materialize_bit_array(
1087        &self,
1088        value: &ConstantBitArrayInstantiation,
1089    ) -> BitArrayExpr {
1090        if !self.owns(value.module()) {
1091            return BitArrayExpr::constant(ConstantBitArrayReference(value.clone()));
1092        }
1093        self.materialize_bit_array_value(self.bit_array(value.template()), value.substitution())
1094    }
1095
1096    fn materialize_bit_array_value(
1097        &self,
1098        value: &ConstantBitArrayValue,
1099        substitution: &TypeSubstitution,
1100    ) -> BitArrayExpr {
1101        match value.kind() {
1102            ConstantBitArrayValueKind::Value(segments) => BitArrayExpr::value(
1103                segments
1104                    .iter()
1105                    .map(|segment| self.materialize_bit_array_segment(segment, substitution))
1106                    .collect(),
1107            ),
1108            ConstantBitArrayValueKind::Reference(value) => {
1109                self.materialize_bit_array(&value.substitute_leaf(substitution))
1110            }
1111        }
1112    }
1113
1114    fn materialize_bit_array_segment(
1115        &self,
1116        segment: &ConstantBitArraySegment,
1117        substitution: &TypeSubstitution,
1118    ) -> BitArraySegment {
1119        match segment {
1120            ConstantBitArraySegment::Int {
1121                value,
1122                bit_size,
1123                endianness,
1124            } => BitArraySegment::Int {
1125                value: self.materialize_int_value(value, substitution),
1126                bit_size: *bit_size,
1127                endianness: *endianness,
1128            },
1129            ConstantBitArraySegment::Float {
1130                value,
1131                bit_size,
1132                endianness,
1133            } => BitArraySegment::Float {
1134                value: self.materialize_float_value(value, substitution),
1135                bit_size: *bit_size,
1136                endianness: *endianness,
1137            },
1138            ConstantBitArraySegment::String { value, encoding } => BitArraySegment::String {
1139                value: self.materialize_string_value(value, substitution),
1140                encoding: *encoding,
1141            },
1142            ConstantBitArraySegment::Bits(value) => {
1143                BitArraySegment::Bits(self.materialize_bit_array_value(value, substitution))
1144            }
1145            ConstantBitArraySegment::SizedBits {
1146                value,
1147                bit_size,
1148                site,
1149            } => BitArraySegment::SizedBits {
1150                value: self.materialize_bit_array_value(value, substitution),
1151                size: BitArrayBitsSize::Fixed(*bit_size),
1152                site: site.clone(),
1153            },
1154        }
1155    }
1156
1157    pub(crate) fn materialize_custom(&self, value: &ConstantCustomInstantiation) -> CustomExpr {
1158        if !self.owns(value.module()) {
1159            return CustomExpr::constant(ConstantCustomReference(value.clone()));
1160        }
1161        self.materialize_custom_value(self.custom(value.template()), value.substitution())
1162    }
1163
1164    fn materialize_custom_value(
1165        &self,
1166        value: &ConstantCustomValue,
1167        substitution: &TypeSubstitution,
1168    ) -> CustomExpr {
1169        match value.kind() {
1170            ConstantCustomValueKind::Construction(construction) => {
1171                let construction = MaterializedConstantCustomConstruction::new(
1172                    construction.constructor().substitute(substitution),
1173                    construction
1174                        .fields()
1175                        .iter()
1176                        .map(|field| self.materialize_value(field, substitution))
1177                        .collect(),
1178                );
1179                CustomExpr::from_construction(
1180                    value.shape().substitute(substitution),
1181                    CustomConstruction::from_constant(construction),
1182                )
1183            }
1184            ConstantCustomValueKind::Reference(value) => {
1185                self.materialize_custom(&value.substitute_custom(substitution))
1186            }
1187        }
1188    }
1189
1190    fn materialize_function_value(
1191        &self,
1192        value: &ConstantFunctionValue,
1193        substitution: &TypeSubstitution,
1194    ) -> FunctionExpr {
1195        match value {
1196            ConstantFunctionValue::Generic(value) => match value.kind() {
1197                TypedConstantFunctionValueKind::Target(reference) => {
1198                    FunctionExpr::reference(reference.substitute(substitution))
1199                }
1200                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1201                    ConstantFunctionInstantiation::Generic(reference.clone())
1202                        .substitute(substitution),
1203                ),
1204            },
1205            ConstantFunctionValue::Int(value) => match value.kind() {
1206                TypedConstantFunctionValueKind::Target(reference) => {
1207                    FunctionExpr::reference(reference.substitute(substitution))
1208                }
1209                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1210                    ConstantFunctionInstantiation::Int(reference.substitute(substitution)),
1211                ),
1212            },
1213            ConstantFunctionValue::String(value) => match value.kind() {
1214                TypedConstantFunctionValueKind::Target(reference) => {
1215                    FunctionExpr::reference(reference.substitute(substitution))
1216                }
1217                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1218                    ConstantFunctionInstantiation::String(reference.substitute(substitution)),
1219                ),
1220            },
1221            ConstantFunctionValue::BitArray(value) => match value.kind() {
1222                TypedConstantFunctionValueKind::Target(reference) => {
1223                    FunctionExpr::reference(reference.substitute(substitution))
1224                }
1225                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1226                    ConstantFunctionInstantiation::BitArray(reference.substitute(substitution)),
1227                ),
1228            },
1229            ConstantFunctionValue::UtfCodepoint(value) => match value.kind() {
1230                TypedConstantFunctionValueKind::Target(reference) => {
1231                    FunctionExpr::reference(reference.substitute(substitution))
1232                }
1233                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1234                    ConstantFunctionInstantiation::UtfCodepoint(reference.substitute(substitution)),
1235                ),
1236            },
1237            ConstantFunctionValue::Custom(value) => match value.kind() {
1238                TypedConstantFunctionValueKind::Target(
1239                    ConstantCustomFunctionTarget::Reference(reference),
1240                ) => FunctionExpr::reference(reference.substitute(substitution)),
1241                TypedConstantFunctionValueKind::Target(
1242                    ConstantCustomFunctionTarget::Constructor(constructor),
1243                ) => FunctionExpr::custom(CustomFunctionExpr::constructor(
1244                    constructor.substitute(substitution),
1245                )),
1246                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1247                    ConstantFunctionInstantiation::Custom(reference.substitute(substitution)),
1248                ),
1249            },
1250            ConstantFunctionValue::External(value) => match value.kind() {
1251                TypedConstantFunctionValueKind::Target(reference) => {
1252                    FunctionExpr::reference(reference.substitute(substitution))
1253                }
1254                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1255                    ConstantFunctionInstantiation::External(reference.substitute(substitution)),
1256                ),
1257            },
1258            ConstantFunctionValue::Float(value) => match value.kind() {
1259                TypedConstantFunctionValueKind::Target(reference) => {
1260                    FunctionExpr::reference(reference.substitute(substitution))
1261                }
1262                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1263                    ConstantFunctionInstantiation::Float(reference.substitute(substitution)),
1264                ),
1265            },
1266            ConstantFunctionValue::Bool(value) => match value.kind() {
1267                TypedConstantFunctionValueKind::Target(reference) => {
1268                    FunctionExpr::reference(reference.substitute(substitution))
1269                }
1270                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1271                    ConstantFunctionInstantiation::Bool(reference.substitute(substitution)),
1272                ),
1273            },
1274            ConstantFunctionValue::Nil(value) => match value.kind() {
1275                TypedConstantFunctionValueKind::Target(reference) => {
1276                    FunctionExpr::reference(reference.substitute(substitution))
1277                }
1278                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1279                    ConstantFunctionInstantiation::Nil(reference.substitute(substitution)),
1280                ),
1281            },
1282            ConstantFunctionValue::Tuple(value) => match value.kind() {
1283                TypedConstantFunctionValueKind::Target(reference) => {
1284                    FunctionExpr::reference(reference.substitute(substitution))
1285                }
1286                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1287                    ConstantFunctionInstantiation::Tuple(reference.substitute(substitution)),
1288                ),
1289            },
1290            ConstantFunctionValue::List(value) => match value.kind() {
1291                TypedConstantFunctionValueKind::Target(reference) => {
1292                    FunctionExpr::reference(reference.substitute(substitution))
1293                }
1294                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1295                    ConstantFunctionInstantiation::List(reference.substitute(substitution)),
1296                ),
1297            },
1298            ConstantFunctionValue::Function(value) => match value.kind() {
1299                TypedConstantFunctionValueKind::Target(reference) => {
1300                    FunctionExpr::reference(reference.substitute(substitution))
1301                }
1302                TypedConstantFunctionValueKind::Reference(reference) => FunctionExpr::constant(
1303                    ConstantFunctionInstantiation::Function(reference.substitute(substitution)),
1304                ),
1305            },
1306        }
1307    }
1308
1309    fn typed_function_reference<Function>(
1310        reference: &FunctionReference,
1311        substitution: &TypeSubstitution,
1312    ) -> TypedFunctionReference<Function> {
1313        TypedFunctionReference::new(reference.substitute(substitution).into_instantiation())
1314    }
1315
1316    pub(crate) fn materialize_generic_function(
1317        &self,
1318        value: &ConstantGenericFunctionInstantiation,
1319    ) -> GenericFunctionExpr {
1320        let type_ = crate::plan::GenericFunctionType::new(
1321            value.shape().argument_shapes().to_vec(),
1322            *value.return_(),
1323        );
1324        match self.generic_function(*value.source()).kind() {
1325            TypedConstantFunctionValueKind::Target(reference) => GenericFunctionExpr::reference(
1326                Self::typed_function_reference(reference, value.substitution()),
1327                type_,
1328            ),
1329            TypedConstantFunctionValueKind::Reference(reference) => GenericFunctionExpr::constant(
1330                reference.substitute_generic(value.substitution(), *value.return_()),
1331                type_,
1332            ),
1333        }
1334    }
1335
1336    pub(crate) fn materialize_int_function(
1337        &self,
1338        value: &ConstantIntFunctionInstantiation,
1339    ) -> IntFunctionExpr {
1340        let type_ = value.shape().type_();
1341        match value.source() {
1342            ConstantFunctionTemplateSource::Generic(source) => {
1343                match self.generic_function(*source).kind() {
1344                    TypedConstantFunctionValueKind::Target(reference) => {
1345                        IntFunctionExpr::reference(Self::typed_function_reference(
1346                            reference,
1347                            value.substitution(),
1348                        ))
1349                    }
1350                    TypedConstantFunctionValueKind::Reference(reference) => {
1351                        IntFunctionExpr::constant(
1352                            reference.specialize(value.substitution(), ()),
1353                            type_,
1354                        )
1355                    }
1356                }
1357            }
1358            ConstantFunctionTemplateSource::Exact(source) => {
1359                match self.int_function(*source).kind() {
1360                    TypedConstantFunctionValueKind::Target(reference) => {
1361                        IntFunctionExpr::reference(Self::typed_function_reference(
1362                            reference,
1363                            value.substitution(),
1364                        ))
1365                    }
1366                    TypedConstantFunctionValueKind::Reference(reference) => {
1367                        let reference = reference.substitute(value.substitution());
1368                        let type_ = reference.shape().type_();
1369                        IntFunctionExpr::constant(reference, type_)
1370                    }
1371                }
1372            }
1373        }
1374    }
1375
1376    pub(crate) fn materialize_string_function(
1377        &self,
1378        value: &ConstantStringFunctionInstantiation,
1379    ) -> StringFunctionExpr {
1380        let type_ = value.shape().type_();
1381        match value.source() {
1382            ConstantFunctionTemplateSource::Generic(source) => {
1383                match self.generic_function(*source).kind() {
1384                    TypedConstantFunctionValueKind::Target(reference) => {
1385                        StringFunctionExpr::reference(Self::typed_function_reference(
1386                            reference,
1387                            value.substitution(),
1388                        ))
1389                    }
1390                    TypedConstantFunctionValueKind::Reference(reference) => {
1391                        StringFunctionExpr::constant(
1392                            reference.specialize(value.substitution(), ()),
1393                            type_,
1394                        )
1395                    }
1396                }
1397            }
1398            ConstantFunctionTemplateSource::Exact(source) => {
1399                match self.string_function(*source).kind() {
1400                    TypedConstantFunctionValueKind::Target(reference) => {
1401                        StringFunctionExpr::reference(Self::typed_function_reference(
1402                            reference,
1403                            value.substitution(),
1404                        ))
1405                    }
1406                    TypedConstantFunctionValueKind::Reference(reference) => {
1407                        let reference = reference.substitute(value.substitution());
1408                        let type_ = reference.shape().type_();
1409                        StringFunctionExpr::constant(reference, type_)
1410                    }
1411                }
1412            }
1413        }
1414    }
1415
1416    pub(crate) fn materialize_bit_array_function(
1417        &self,
1418        value: &ConstantBitArrayFunctionInstantiation,
1419    ) -> BitArrayFunctionExpr {
1420        let type_ = value.shape().type_();
1421        match value.source() {
1422            ConstantFunctionTemplateSource::Generic(source) => {
1423                match self.generic_function(*source).kind() {
1424                    TypedConstantFunctionValueKind::Target(reference) => {
1425                        BitArrayFunctionExpr::reference(Self::typed_function_reference(
1426                            reference,
1427                            value.substitution(),
1428                        ))
1429                    }
1430                    TypedConstantFunctionValueKind::Reference(reference) => {
1431                        BitArrayFunctionExpr::constant(
1432                            reference.specialize(value.substitution(), ()),
1433                            type_,
1434                        )
1435                    }
1436                }
1437            }
1438            ConstantFunctionTemplateSource::Exact(source) => {
1439                match self.bit_array_function(*source).kind() {
1440                    TypedConstantFunctionValueKind::Target(reference) => {
1441                        BitArrayFunctionExpr::reference(Self::typed_function_reference(
1442                            reference,
1443                            value.substitution(),
1444                        ))
1445                    }
1446                    TypedConstantFunctionValueKind::Reference(reference) => {
1447                        let reference = reference.substitute(value.substitution());
1448                        let type_ = reference.shape().type_();
1449                        BitArrayFunctionExpr::constant(reference, type_)
1450                    }
1451                }
1452            }
1453        }
1454    }
1455
1456    pub(crate) fn materialize_utf_codepoint_function(
1457        &self,
1458        value: &ConstantUtfCodepointFunctionInstantiation,
1459    ) -> UtfCodepointFunctionExpr {
1460        let type_ = value.shape().type_();
1461        match value.source() {
1462            ConstantFunctionTemplateSource::Generic(source) => {
1463                match self.generic_function(*source).kind() {
1464                    TypedConstantFunctionValueKind::Target(reference) => {
1465                        UtfCodepointFunctionExpr::reference(Self::typed_function_reference(
1466                            reference,
1467                            value.substitution(),
1468                        ))
1469                    }
1470                    TypedConstantFunctionValueKind::Reference(reference) => {
1471                        UtfCodepointFunctionExpr::constant(
1472                            reference.specialize(value.substitution(), ()),
1473                            type_,
1474                        )
1475                    }
1476                }
1477            }
1478            ConstantFunctionTemplateSource::Exact(source) => {
1479                match self.utf_codepoint_function(*source).kind() {
1480                    TypedConstantFunctionValueKind::Target(reference) => {
1481                        UtfCodepointFunctionExpr::reference(Self::typed_function_reference(
1482                            reference,
1483                            value.substitution(),
1484                        ))
1485                    }
1486                    TypedConstantFunctionValueKind::Reference(reference) => {
1487                        let reference = reference.substitute(value.substitution());
1488                        let type_ = reference.shape().type_();
1489                        UtfCodepointFunctionExpr::constant(reference, type_)
1490                    }
1491                }
1492            }
1493        }
1494    }
1495
1496    pub(crate) fn materialize_float_function(
1497        &self,
1498        value: &ConstantFloatFunctionInstantiation,
1499    ) -> FloatFunctionExpr {
1500        let type_ = value.shape().type_();
1501        match value.source() {
1502            ConstantFunctionTemplateSource::Generic(source) => {
1503                match self.generic_function(*source).kind() {
1504                    TypedConstantFunctionValueKind::Target(reference) => {
1505                        FloatFunctionExpr::reference(Self::typed_function_reference(
1506                            reference,
1507                            value.substitution(),
1508                        ))
1509                    }
1510                    TypedConstantFunctionValueKind::Reference(reference) => {
1511                        FloatFunctionExpr::constant(
1512                            reference.specialize(value.substitution(), ()),
1513                            type_,
1514                        )
1515                    }
1516                }
1517            }
1518            ConstantFunctionTemplateSource::Exact(source) => {
1519                match self.float_function(*source).kind() {
1520                    TypedConstantFunctionValueKind::Target(reference) => {
1521                        FloatFunctionExpr::reference(Self::typed_function_reference(
1522                            reference,
1523                            value.substitution(),
1524                        ))
1525                    }
1526                    TypedConstantFunctionValueKind::Reference(reference) => {
1527                        let reference = reference.substitute(value.substitution());
1528                        let type_ = reference.shape().type_();
1529                        FloatFunctionExpr::constant(reference, type_)
1530                    }
1531                }
1532            }
1533        }
1534    }
1535
1536    pub(crate) fn materialize_bool_function(
1537        &self,
1538        value: &ConstantBoolFunctionInstantiation,
1539    ) -> BoolFunctionExpr {
1540        let type_ = value.shape().type_();
1541        match value.source() {
1542            ConstantFunctionTemplateSource::Generic(source) => {
1543                match self.generic_function(*source).kind() {
1544                    TypedConstantFunctionValueKind::Target(reference) => {
1545                        BoolFunctionExpr::reference(Self::typed_function_reference(
1546                            reference,
1547                            value.substitution(),
1548                        ))
1549                    }
1550                    TypedConstantFunctionValueKind::Reference(reference) => {
1551                        BoolFunctionExpr::constant(
1552                            reference.specialize(value.substitution(), ()),
1553                            type_,
1554                        )
1555                    }
1556                }
1557            }
1558            ConstantFunctionTemplateSource::Exact(source) => {
1559                match self.bool_function(*source).kind() {
1560                    TypedConstantFunctionValueKind::Target(reference) => {
1561                        BoolFunctionExpr::reference(Self::typed_function_reference(
1562                            reference,
1563                            value.substitution(),
1564                        ))
1565                    }
1566                    TypedConstantFunctionValueKind::Reference(reference) => {
1567                        let reference = reference.substitute(value.substitution());
1568                        let type_ = reference.shape().type_();
1569                        BoolFunctionExpr::constant(reference, type_)
1570                    }
1571                }
1572            }
1573        }
1574    }
1575
1576    pub(crate) fn materialize_nil_function(
1577        &self,
1578        value: &ConstantNilFunctionInstantiation,
1579    ) -> NilFunctionExpr {
1580        let type_ = value.shape().type_();
1581        match value.source() {
1582            ConstantFunctionTemplateSource::Generic(source) => {
1583                match self.generic_function(*source).kind() {
1584                    TypedConstantFunctionValueKind::Target(reference) => {
1585                        NilFunctionExpr::reference(Self::typed_function_reference(
1586                            reference,
1587                            value.substitution(),
1588                        ))
1589                    }
1590                    TypedConstantFunctionValueKind::Reference(reference) => {
1591                        NilFunctionExpr::constant(
1592                            reference.specialize(value.substitution(), ()),
1593                            type_,
1594                        )
1595                    }
1596                }
1597            }
1598            ConstantFunctionTemplateSource::Exact(source) => {
1599                match self.nil_function(*source).kind() {
1600                    TypedConstantFunctionValueKind::Target(reference) => {
1601                        NilFunctionExpr::reference(Self::typed_function_reference(
1602                            reference,
1603                            value.substitution(),
1604                        ))
1605                    }
1606                    TypedConstantFunctionValueKind::Reference(reference) => {
1607                        let reference = reference.substitute(value.substitution());
1608                        let type_ = reference.shape().type_();
1609                        NilFunctionExpr::constant(reference, type_)
1610                    }
1611                }
1612            }
1613        }
1614    }
1615
1616    pub(crate) fn materialize_tuple_function(
1617        &self,
1618        value: &ConstantTupleFunctionInstantiation,
1619    ) -> TupleFunctionExpr {
1620        let type_ = value.shape().type_();
1621        match value.source() {
1622            ConstantFunctionTemplateSource::Generic(source) => {
1623                match self.generic_function(*source).kind() {
1624                    TypedConstantFunctionValueKind::Target(reference) => {
1625                        TupleFunctionExpr::reference(Self::typed_function_reference(
1626                            reference,
1627                            value.substitution(),
1628                        ))
1629                    }
1630                    TypedConstantFunctionValueKind::Reference(reference) => {
1631                        TupleFunctionExpr::constant(
1632                            reference.specialize(value.substitution(), value.return_().clone()),
1633                            type_,
1634                        )
1635                    }
1636                }
1637            }
1638            ConstantFunctionTemplateSource::Exact(source) => {
1639                match self.tuple_function(*source).kind() {
1640                    TypedConstantFunctionValueKind::Target(reference) => {
1641                        TupleFunctionExpr::reference(Self::typed_function_reference(
1642                            reference,
1643                            value.substitution(),
1644                        ))
1645                    }
1646                    TypedConstantFunctionValueKind::Reference(reference) => {
1647                        let reference = reference.substitute(value.substitution());
1648                        let type_ = reference.shape().type_();
1649                        TupleFunctionExpr::constant(reference, type_)
1650                    }
1651                }
1652            }
1653        }
1654    }
1655
1656    pub(crate) fn materialize_list_function(
1657        &self,
1658        value: &ConstantListFunctionInstantiation,
1659    ) -> ListFunctionExpr {
1660        let type_ = value.shape().type_();
1661        let item_type = value.return_().value_type();
1662        match value.source() {
1663            ConstantFunctionTemplateSource::Generic(source) => {
1664                match self.generic_function(*source).kind() {
1665                    TypedConstantFunctionValueKind::Target(reference) => {
1666                        ListFunctionExpr::reference(
1667                            Self::typed_function_reference(reference, value.substitution()),
1668                            item_type,
1669                        )
1670                    }
1671                    TypedConstantFunctionValueKind::Reference(reference) => {
1672                        ListFunctionExpr::constant(
1673                            reference.specialize(value.substitution(), value.return_().clone()),
1674                            type_,
1675                            item_type,
1676                        )
1677                    }
1678                }
1679            }
1680            ConstantFunctionTemplateSource::Exact(source) => {
1681                match self.list_function(*source).kind() {
1682                    TypedConstantFunctionValueKind::Target(reference) => {
1683                        ListFunctionExpr::reference(
1684                            Self::typed_function_reference(reference, value.substitution()),
1685                            item_type,
1686                        )
1687                    }
1688                    TypedConstantFunctionValueKind::Reference(reference) => {
1689                        let reference = reference.substitute(value.substitution());
1690                        let type_ = reference.shape().type_();
1691                        let item_type = reference.return_().value_type();
1692                        ListFunctionExpr::constant(reference, type_, item_type)
1693                    }
1694                }
1695            }
1696        }
1697    }
1698
1699    pub(crate) fn materialize_custom_function(
1700        &self,
1701        value: &ConstantCustomFunctionInstantiation,
1702    ) -> CustomFunctionExpr {
1703        let type_ = crate::plan::CustomFunctionType::from_shapes(
1704            value.shape().argument_shapes().to_vec(),
1705            value.return_().clone(),
1706        );
1707        match value.source() {
1708            ConstantFunctionTemplateSource::Generic(source) => {
1709                match self.generic_function(*source).kind() {
1710                    TypedConstantFunctionValueKind::Target(reference) => {
1711                        CustomFunctionExpr::reference(
1712                            Self::typed_function_reference(reference, value.substitution()),
1713                            value.return_().clone(),
1714                        )
1715                    }
1716                    TypedConstantFunctionValueKind::Reference(reference) => {
1717                        CustomFunctionExpr::constant(
1718                            reference.specialize(value.substitution(), value.return_().clone()),
1719                            type_,
1720                        )
1721                    }
1722                }
1723            }
1724            ConstantFunctionTemplateSource::Exact(source) => {
1725                match self.custom_function(*source).kind() {
1726                    TypedConstantFunctionValueKind::Target(
1727                        ConstantCustomFunctionTarget::Reference(reference),
1728                    ) => CustomFunctionExpr::reference(
1729                        Self::typed_function_reference(reference, value.substitution()),
1730                        value.return_().clone(),
1731                    ),
1732                    TypedConstantFunctionValueKind::Target(
1733                        ConstantCustomFunctionTarget::Constructor(constructor),
1734                    ) => CustomFunctionExpr::constructor(
1735                        constructor.substitute(value.substitution()),
1736                    ),
1737                    TypedConstantFunctionValueKind::Reference(reference) => {
1738                        let reference = reference.substitute(value.substitution());
1739                        let type_ = crate::plan::CustomFunctionType::from_shapes(
1740                            reference.shape().argument_shapes().to_vec(),
1741                            reference.return_().clone(),
1742                        );
1743                        CustomFunctionExpr::constant(reference, type_)
1744                    }
1745                }
1746            }
1747        }
1748    }
1749
1750    pub(crate) fn materialize_external_function(
1751        &self,
1752        value: &ConstantExternalFunctionInstantiation,
1753    ) -> ExternalFunctionExpr {
1754        let type_ = crate::plan::ExternalFunctionType::from_shapes(
1755            value.shape().argument_shapes().to_vec(),
1756            value.return_().clone(),
1757        );
1758        match value.source() {
1759            ConstantFunctionTemplateSource::Generic(source) => {
1760                match self.generic_function(*source).kind() {
1761                    TypedConstantFunctionValueKind::Target(reference) => {
1762                        ExternalFunctionExpr::reference(
1763                            Self::typed_function_reference(reference, value.substitution()),
1764                            value.return_().clone(),
1765                        )
1766                    }
1767                    TypedConstantFunctionValueKind::Reference(reference) => {
1768                        ExternalFunctionExpr::constant(
1769                            reference.specialize(value.substitution(), value.return_().clone()),
1770                            type_,
1771                        )
1772                    }
1773                }
1774            }
1775            ConstantFunctionTemplateSource::Exact(source) => {
1776                match self.external_function(*source).kind() {
1777                    TypedConstantFunctionValueKind::Target(reference) => {
1778                        ExternalFunctionExpr::reference(
1779                            Self::typed_function_reference(reference, value.substitution()),
1780                            value.return_().clone(),
1781                        )
1782                    }
1783                    TypedConstantFunctionValueKind::Reference(reference) => {
1784                        let reference = reference.substitute(value.substitution());
1785                        let type_ = crate::plan::ExternalFunctionType::from_shapes(
1786                            reference.shape().argument_shapes().to_vec(),
1787                            reference.return_().clone(),
1788                        );
1789                        ExternalFunctionExpr::constant(reference, type_)
1790                    }
1791                }
1792            }
1793        }
1794    }
1795
1796    pub(crate) fn materialize_function_function(
1797        &self,
1798        value: &ConstantFunctionFunctionInstantiation,
1799    ) -> FunctionFunctionExpr {
1800        let type_ = crate::plan::FunctionFunctionType::from_shapes(
1801            value.shape().argument_shapes().to_vec(),
1802            value.return_().as_ref().clone(),
1803        );
1804        match value.source() {
1805            ConstantFunctionTemplateSource::Generic(source) => {
1806                match self.generic_function(*source).kind() {
1807                    TypedConstantFunctionValueKind::Target(reference) => {
1808                        FunctionFunctionExpr::reference(
1809                            Self::typed_function_reference(reference, value.substitution()),
1810                            value.return_().type_(),
1811                        )
1812                    }
1813                    TypedConstantFunctionValueKind::Reference(reference) => {
1814                        FunctionFunctionExpr::constant(
1815                            reference.specialize(value.substitution(), value.return_().clone()),
1816                            type_,
1817                        )
1818                    }
1819                }
1820            }
1821            ConstantFunctionTemplateSource::Exact(source) => {
1822                match self.function_function(*source).kind() {
1823                    TypedConstantFunctionValueKind::Target(reference) => {
1824                        FunctionFunctionExpr::reference(
1825                            Self::typed_function_reference(reference, value.substitution()),
1826                            value.return_().type_(),
1827                        )
1828                    }
1829                    TypedConstantFunctionValueKind::Reference(reference) => {
1830                        let reference = reference.substitute(value.substitution());
1831                        let type_ = crate::plan::FunctionFunctionType::from_shapes(
1832                            reference.shape().argument_shapes().to_vec(),
1833                            reference.return_().as_ref().clone(),
1834                        );
1835                        FunctionFunctionExpr::constant(reference, type_)
1836                    }
1837                }
1838            }
1839        }
1840    }
1841
1842    pub(crate) fn materialize_generic_list(
1843        &self,
1844        value: &ConstantGenericListInstantiation,
1845    ) -> GenericListExpr {
1846        if !self.owns(value.module()) {
1847            let parameter = *value.item_shape();
1848            return GenericListExpr::constant(
1849                ValueShape::Parameter(parameter),
1850                GenericListItem::new(parameter),
1851                value.clone(),
1852            );
1853        }
1854        self.materialize_generic_parameter_list(
1855            self.generic_list(*value.source()),
1856            value.substitution(),
1857            *value.item_shape(),
1858        )
1859    }
1860
1861    fn materialize_list_value(
1862        &self,
1863        value: &ConstantListValue,
1864        substitution: &TypeSubstitution,
1865    ) -> ListExpr {
1866        match value {
1867            ConstantListValue::Generic(value) => {
1868                let item_shape = ValueShape::Parameter(value.parameter()).substitute(substitution);
1869                self.materialize_generic_list_value(value, substitution, &item_shape)
1870            }
1871            ConstantListValue::ParameterList(value) => {
1872                match ValueShape::Parameter(*value.item_shape())
1873                    .substitute(substitution)
1874                    .representation()
1875                {
1876                    crate::plan::ValueRepresentation::Uninhabited(parameter) => {
1877                        ListExpr::ParameterList(self.materialize_parameter_list_list_value(
1878                            value,
1879                            substitution,
1880                            parameter,
1881                        ))
1882                    }
1883                    crate::plan::ValueRepresentation::Stored(shape) => {
1884                        ListExpr::List(self.materialize_parameter_list_list_value_as_stored(
1885                            value,
1886                            substitution,
1887                            &shape,
1888                        ))
1889                    }
1890                }
1891            }
1892            ConstantListValue::Int(value) => {
1893                ListExpr::Int(self.materialize_int_list_value(value, substitution))
1894            }
1895            ConstantListValue::String(value) => {
1896                ListExpr::String(self.materialize_string_list_value(value, substitution))
1897            }
1898            ConstantListValue::BitArray(value) => {
1899                ListExpr::BitArray(self.materialize_bit_array_list_value(value, substitution))
1900            }
1901            ConstantListValue::UtfCodepoint(value) => ListExpr::UtfCodepoint(
1902                self.materialize_utf_codepoint_list_value(value, substitution),
1903            ),
1904            ConstantListValue::Custom(value) => {
1905                ListExpr::Custom(self.materialize_custom_list_value(value, substitution))
1906            }
1907            ConstantListValue::External(value) => {
1908                ListExpr::External(self.materialize_external_list_value(value, substitution))
1909            }
1910            ConstantListValue::Float(value) => {
1911                ListExpr::Float(self.materialize_float_list_value(value, substitution))
1912            }
1913            ConstantListValue::Bool(value) => {
1914                ListExpr::Bool(self.materialize_bool_list_value(value, substitution))
1915            }
1916            ConstantListValue::Nil(value) => {
1917                ListExpr::Nil(self.materialize_nil_list_value(value, substitution))
1918            }
1919            ConstantListValue::Tuple(value) => {
1920                ListExpr::Tuple(self.materialize_tuple_list_value(value, substitution))
1921            }
1922            ConstantListValue::List(value) => {
1923                ListExpr::List(self.materialize_list_list_value(value, substitution))
1924            }
1925            ConstantListValue::Function(value) => {
1926                ListExpr::Function(self.materialize_function_list_value(value, substitution))
1927            }
1928        }
1929    }
1930
1931    fn materialize_generic_list_value(
1932        &self,
1933        value: &ConstantGenericListValue,
1934        substitution: &TypeSubstitution,
1935        item_shape: &ValueShape,
1936    ) -> ListExpr {
1937        match item_shape {
1938            ValueShape::Parameter(parameter) => ListExpr::Generic(
1939                self.materialize_generic_parameter_list(value, substitution, *parameter),
1940            ),
1941            ValueShape::Int => {
1942                ListExpr::Int(self.materialize_generic_int_list(value, substitution))
1943            }
1944            ValueShape::String => {
1945                ListExpr::String(self.materialize_generic_string_list(value, substitution))
1946            }
1947            ValueShape::BitArray => {
1948                ListExpr::BitArray(self.materialize_generic_bit_array_list(value, substitution))
1949            }
1950            ValueShape::UtfCodepoint => ListExpr::UtfCodepoint(
1951                self.materialize_generic_utf_codepoint_list(value, substitution),
1952            ),
1953            ValueShape::Custom(shape) => {
1954                ListExpr::Custom(self.materialize_generic_custom_list(value, substitution, shape))
1955            }
1956            ValueShape::External(shape) => ListExpr::External(
1957                self.materialize_generic_external_list(value, substitution, shape),
1958            ),
1959            ValueShape::Float => {
1960                ListExpr::Float(self.materialize_generic_float_list(value, substitution))
1961            }
1962            ValueShape::Bool => {
1963                ListExpr::Bool(self.materialize_generic_bool_list(value, substitution))
1964            }
1965            ValueShape::Nil => {
1966                ListExpr::Nil(self.materialize_generic_nil_list(value, substitution))
1967            }
1968            ValueShape::Tuple(shape) => {
1969                ListExpr::Tuple(self.materialize_generic_tuple_list(value, substitution, shape))
1970            }
1971            ValueShape::List(shape) => match shape.representation() {
1972                crate::plan::ValueRepresentation::Uninhabited(parameter) => {
1973                    ListExpr::ParameterList(self.materialize_generic_parameter_list_list(
1974                        value,
1975                        substitution,
1976                        parameter,
1977                    ))
1978                }
1979                crate::plan::ValueRepresentation::Stored(item_shape) => ListExpr::List(
1980                    self.materialize_generic_list_list(value, substitution, &item_shape),
1981                ),
1982            },
1983            ValueShape::Function(shape) => ListExpr::Function(
1984                self.materialize_generic_function_list(value, substitution, shape),
1985            ),
1986        }
1987    }
1988
1989    fn materialize_generic_stored_list_value(
1990        &self,
1991        value: &ConstantGenericListValue,
1992        substitution: &TypeSubstitution,
1993        shape: &crate::plan::ValueStorageShape,
1994    ) -> StoredListExpr {
1995        match shape {
1996            crate::plan::ValueStorageShape::Int => {
1997                StoredListExpr::Int(self.materialize_generic_int_list(value, substitution))
1998            }
1999            crate::plan::ValueStorageShape::Float => {
2000                StoredListExpr::Float(self.materialize_generic_float_list(value, substitution))
2001            }
2002            crate::plan::ValueStorageShape::String => {
2003                StoredListExpr::String(self.materialize_generic_string_list(value, substitution))
2004            }
2005            crate::plan::ValueStorageShape::BitArray => StoredListExpr::BitArray(
2006                self.materialize_generic_bit_array_list(value, substitution),
2007            ),
2008            crate::plan::ValueStorageShape::UtfCodepoint => StoredListExpr::UtfCodepoint(
2009                self.materialize_generic_utf_codepoint_list(value, substitution),
2010            ),
2011            crate::plan::ValueStorageShape::Custom(shape) => StoredListExpr::Custom(
2012                self.materialize_generic_custom_list(value, substitution, shape),
2013            ),
2014            crate::plan::ValueStorageShape::External(shape) => StoredListExpr::External(
2015                self.materialize_generic_external_list(value, substitution, shape),
2016            ),
2017            crate::plan::ValueStorageShape::Bool => {
2018                StoredListExpr::Bool(self.materialize_generic_bool_list(value, substitution))
2019            }
2020            crate::plan::ValueStorageShape::Nil => {
2021                StoredListExpr::Nil(self.materialize_generic_nil_list(value, substitution))
2022            }
2023            crate::plan::ValueStorageShape::Tuple(shape) => StoredListExpr::Tuple(
2024                self.materialize_generic_tuple_list(value, substitution, shape),
2025            ),
2026            crate::plan::ValueStorageShape::List(shape) => match shape.representation() {
2027                crate::plan::ValueRepresentation::Uninhabited(parameter) => {
2028                    StoredListExpr::ParameterList(self.materialize_generic_parameter_list_list(
2029                        value,
2030                        substitution,
2031                        parameter,
2032                    ))
2033                }
2034                crate::plan::ValueRepresentation::Stored(shape) => StoredListExpr::List(
2035                    self.materialize_generic_list_list(value, substitution, &shape),
2036                ),
2037            },
2038            crate::plan::ValueStorageShape::Function(shape) => StoredListExpr::Function(
2039                self.materialize_generic_function_list(value, substitution, shape),
2040            ),
2041        }
2042    }
2043
2044    fn materialize_generic_parameter_list(
2045        &self,
2046        value: &ConstantGenericListValue,
2047        substitution: &TypeSubstitution,
2048        parameter: crate::plan::TypeParameterId,
2049    ) -> GenericListExpr {
2050        match value.kind() {
2051            ConstantGenericListValueKind::Empty => {
2052                GenericListExpr::value(GenericListItem::new(parameter), Vec::new())
2053                    .with_item_shape(ValueShape::Parameter(parameter))
2054            }
2055            ConstantGenericListValueKind::Reference(value) => {
2056                self.materialize_generic_list(&value.retarget_generic(substitution, parameter))
2057            }
2058        }
2059    }
2060
2061    fn materialize_generic_int_list(
2062        &self,
2063        value: &ConstantGenericListValue,
2064        substitution: &TypeSubstitution,
2065    ) -> IntListExpr {
2066        match value.kind() {
2067            ConstantGenericListValueKind::Empty => {
2068                IntListExpr::value(IntListItem, Vec::new()).with_item_shape(ValueShape::Int)
2069            }
2070            ConstantGenericListValueKind::Reference(value) => {
2071                self.materialize_int_list(&value.retarget(substitution, ()))
2072            }
2073        }
2074    }
2075
2076    fn materialize_generic_string_list(
2077        &self,
2078        value: &ConstantGenericListValue,
2079        substitution: &TypeSubstitution,
2080    ) -> StringListExpr {
2081        match value.kind() {
2082            ConstantGenericListValueKind::Empty => {
2083                StringListExpr::value(StringListItem, Vec::new())
2084                    .with_item_shape(ValueShape::String)
2085            }
2086            ConstantGenericListValueKind::Reference(value) => {
2087                self.materialize_string_list(&value.retarget(substitution, ()))
2088            }
2089        }
2090    }
2091
2092    fn materialize_generic_bit_array_list(
2093        &self,
2094        value: &ConstantGenericListValue,
2095        substitution: &TypeSubstitution,
2096    ) -> BitArrayListExpr {
2097        match value.kind() {
2098            ConstantGenericListValueKind::Empty => {
2099                BitArrayListExpr::value(BitArrayListItem, Vec::new())
2100                    .with_item_shape(ValueShape::BitArray)
2101            }
2102            ConstantGenericListValueKind::Reference(value) => {
2103                self.materialize_bit_array_list(&value.retarget(substitution, ()))
2104            }
2105        }
2106    }
2107
2108    fn materialize_generic_utf_codepoint_list(
2109        &self,
2110        value: &ConstantGenericListValue,
2111        substitution: &TypeSubstitution,
2112    ) -> UtfCodepointListExpr {
2113        match value.kind() {
2114            ConstantGenericListValueKind::Empty => {
2115                UtfCodepointListExpr::value(UtfCodepointListItem, Vec::new())
2116                    .with_item_shape(ValueShape::UtfCodepoint)
2117            }
2118            ConstantGenericListValueKind::Reference(value) => {
2119                self.materialize_utf_codepoint_list(&value.retarget(substitution, ()))
2120            }
2121        }
2122    }
2123
2124    fn materialize_generic_custom_list(
2125        &self,
2126        value: &ConstantGenericListValue,
2127        substitution: &TypeSubstitution,
2128        shape: &CustomValueShape,
2129    ) -> CustomListExpr {
2130        match value.kind() {
2131            ConstantGenericListValueKind::Empty => {
2132                CustomListExpr::value(CustomListItem::new(shape.type_().clone()), Vec::new())
2133                    .with_item_shape(ValueShape::Custom(shape.clone()))
2134            }
2135            ConstantGenericListValueKind::Reference(value) => {
2136                self.materialize_custom_list(&value.retarget(substitution, shape.clone()))
2137            }
2138        }
2139    }
2140
2141    fn materialize_generic_external_list(
2142        &self,
2143        value: &ConstantGenericListValue,
2144        substitution: &TypeSubstitution,
2145        shape: &ExternalValueShape,
2146    ) -> ExternalListExpr {
2147        match value.kind() {
2148            ConstantGenericListValueKind::Empty => {
2149                ExternalListExpr::value(ExternalListItem::new(shape.type_().clone()), Vec::new())
2150                    .with_item_shape(ValueShape::External(shape.clone()))
2151            }
2152            ConstantGenericListValueKind::Reference(value) => {
2153                self.materialize_external_list(&value.retarget(substitution, shape.clone()))
2154            }
2155        }
2156    }
2157
2158    fn materialize_generic_float_list(
2159        &self,
2160        value: &ConstantGenericListValue,
2161        substitution: &TypeSubstitution,
2162    ) -> FloatListExpr {
2163        match value.kind() {
2164            ConstantGenericListValueKind::Empty => {
2165                FloatListExpr::value(FloatListItem, Vec::new()).with_item_shape(ValueShape::Float)
2166            }
2167            ConstantGenericListValueKind::Reference(value) => {
2168                self.materialize_float_list(&value.retarget(substitution, ()))
2169            }
2170        }
2171    }
2172
2173    fn materialize_generic_bool_list(
2174        &self,
2175        value: &ConstantGenericListValue,
2176        substitution: &TypeSubstitution,
2177    ) -> BoolListExpr {
2178        match value.kind() {
2179            ConstantGenericListValueKind::Empty => {
2180                BoolListExpr::value(BoolListItem, Vec::new()).with_item_shape(ValueShape::Bool)
2181            }
2182            ConstantGenericListValueKind::Reference(value) => {
2183                self.materialize_bool_list(&value.retarget(substitution, ()))
2184            }
2185        }
2186    }
2187
2188    fn materialize_generic_nil_list(
2189        &self,
2190        value: &ConstantGenericListValue,
2191        substitution: &TypeSubstitution,
2192    ) -> NilListExpr {
2193        match value.kind() {
2194            ConstantGenericListValueKind::Empty => {
2195                NilListExpr::value(NilListItem, Vec::new()).with_item_shape(ValueShape::Nil)
2196            }
2197            ConstantGenericListValueKind::Reference(value) => {
2198                self.materialize_nil_list(&value.retarget(substitution, ()))
2199            }
2200        }
2201    }
2202
2203    fn materialize_generic_tuple_list(
2204        &self,
2205        value: &ConstantGenericListValue,
2206        substitution: &TypeSubstitution,
2207        shape: &[ValueShape],
2208    ) -> TupleListExpr {
2209        match value.kind() {
2210            ConstantGenericListValueKind::Empty => TupleListExpr::value(
2211                TupleListItem::new(shape.iter().map(ValueShape::value_type).collect()),
2212                Vec::new(),
2213            )
2214            .with_item_shape(ValueShape::Tuple(shape.to_vec().into_boxed_slice())),
2215            ConstantGenericListValueKind::Reference(value) => self.materialize_tuple_list(
2216                &value.retarget(substitution, shape.to_vec().into_boxed_slice()),
2217            ),
2218        }
2219    }
2220
2221    fn materialize_generic_list_list(
2222        &self,
2223        value: &ConstantGenericListValue,
2224        substitution: &TypeSubstitution,
2225        shape: &crate::plan::ValueStorageShape,
2226    ) -> ListListExpr {
2227        match value.kind() {
2228            ConstantGenericListValueKind::Empty => {
2229                ListListExpr::value(ListListItem::new(shape.clone()), Vec::new())
2230                    .with_item_shape(ValueShape::List(Box::new(shape.to_value_shape())))
2231            }
2232            ConstantGenericListValueKind::Reference(value) => {
2233                self.materialize_list_list(&value.retarget_nested(substitution, shape.clone()))
2234            }
2235        }
2236    }
2237
2238    fn materialize_generic_parameter_list_list(
2239        &self,
2240        value: &ConstantGenericListValue,
2241        substitution: &TypeSubstitution,
2242        parameter: crate::plan::TypeParameterId,
2243    ) -> crate::plan::ParameterListListExpr {
2244        match value.kind() {
2245            ConstantGenericListValueKind::Empty => crate::plan::ParameterListListExpr::value(
2246                crate::plan::ParameterListListItem::new(parameter),
2247                Vec::new(),
2248            )
2249            .with_item_shape(ValueShape::List(Box::new(ValueShape::Parameter(parameter)))),
2250            ConstantGenericListValueKind::Reference(value) => {
2251                self.materialize_parameter_list_list(&value.retarget(substitution, parameter))
2252            }
2253        }
2254    }
2255
2256    fn materialize_generic_function_list(
2257        &self,
2258        value: &ConstantGenericListValue,
2259        substitution: &TypeSubstitution,
2260        shape: &FunctionShape,
2261    ) -> FunctionListExpr {
2262        match value.kind() {
2263            ConstantGenericListValueKind::Empty => {
2264                FunctionListExpr::value(FunctionListItem::new(shape.type_()), Vec::new())
2265                    .with_item_shape(ValueShape::Function(Box::new(shape.clone())))
2266            }
2267            ConstantGenericListValueKind::Reference(value) => {
2268                self.materialize_function_list(&value.retarget(substitution, shape.clone()))
2269            }
2270        }
2271    }
2272
2273    pub(crate) fn materialize_int_list(&self, value: &ConstantIntListInstantiation) -> IntListExpr {
2274        if !self.owns(value.module()) {
2275            return IntListExpr::constant(ValueShape::Int, IntListItem, value.clone());
2276        }
2277        match value.source() {
2278            ConstantListTemplateSource::Generic(source) => {
2279                self.materialize_generic_int_list(self.generic_list(*source), value.substitution())
2280            }
2281            ConstantListTemplateSource::Exact(source) => {
2282                self.materialize_int_list_value(self.int_list(*source), value.substitution())
2283            }
2284        }
2285    }
2286
2287    fn materialize_int_list_value(
2288        &self,
2289        value: &ConstantIntListValue,
2290        substitution: &TypeSubstitution,
2291    ) -> IntListExpr {
2292        match value.kind() {
2293            TypedConstantListValueKind::Value(elements) => IntListExpr::value(
2294                IntListItem,
2295                elements
2296                    .iter()
2297                    .map(|value| self.materialize_int_value(value, substitution))
2298                    .collect(),
2299            ),
2300            TypedConstantListValueKind::Spread { elements, tail } => IntListExpr::spread(
2301                elements.mapped_ref(|value| self.materialize_int_value(value, substitution)),
2302                self.materialize_int_list_value(tail, substitution),
2303            ),
2304            TypedConstantListValueKind::Reference(value) => {
2305                self.materialize_int_list(&value.substitute_leaf(substitution))
2306            }
2307        }
2308    }
2309
2310    pub(crate) fn materialize_string_list(
2311        &self,
2312        value: &ConstantStringListInstantiation,
2313    ) -> StringListExpr {
2314        if !self.owns(value.module()) {
2315            return StringListExpr::constant(ValueShape::String, StringListItem, value.clone());
2316        }
2317        match value.source() {
2318            ConstantListTemplateSource::Generic(source) => self
2319                .materialize_generic_string_list(self.generic_list(*source), value.substitution()),
2320            ConstantListTemplateSource::Exact(source) => {
2321                self.materialize_string_list_value(self.string_list(*source), value.substitution())
2322            }
2323        }
2324    }
2325
2326    fn materialize_string_list_value(
2327        &self,
2328        value: &ConstantStringListValue,
2329        substitution: &TypeSubstitution,
2330    ) -> StringListExpr {
2331        match value.kind() {
2332            TypedConstantListValueKind::Value(elements) => StringListExpr::value(
2333                StringListItem,
2334                elements
2335                    .iter()
2336                    .map(|value| self.materialize_string_value(value, substitution))
2337                    .collect(),
2338            ),
2339            TypedConstantListValueKind::Spread { elements, tail } => StringListExpr::spread(
2340                elements.mapped_ref(|value| self.materialize_string_value(value, substitution)),
2341                self.materialize_string_list_value(tail, substitution),
2342            ),
2343            TypedConstantListValueKind::Reference(value) => {
2344                self.materialize_string_list(&value.substitute_leaf(substitution))
2345            }
2346        }
2347    }
2348
2349    pub(crate) fn materialize_bit_array_list(
2350        &self,
2351        value: &ConstantBitArrayListInstantiation,
2352    ) -> BitArrayListExpr {
2353        if !self.owns(value.module()) {
2354            return BitArrayListExpr::constant(
2355                ValueShape::BitArray,
2356                BitArrayListItem,
2357                value.clone(),
2358            );
2359        }
2360        match value.source() {
2361            ConstantListTemplateSource::Generic(source) => self.materialize_generic_bit_array_list(
2362                self.generic_list(*source),
2363                value.substitution(),
2364            ),
2365            ConstantListTemplateSource::Exact(source) => self.materialize_bit_array_list_value(
2366                self.bit_array_list(*source),
2367                value.substitution(),
2368            ),
2369        }
2370    }
2371
2372    fn materialize_bit_array_list_value(
2373        &self,
2374        value: &ConstantBitArrayListValue,
2375        substitution: &TypeSubstitution,
2376    ) -> BitArrayListExpr {
2377        match value.kind() {
2378            TypedConstantListValueKind::Value(elements) => BitArrayListExpr::value(
2379                BitArrayListItem,
2380                elements
2381                    .iter()
2382                    .map(|value| self.materialize_bit_array_value(value, substitution))
2383                    .collect(),
2384            ),
2385            TypedConstantListValueKind::Spread { elements, tail } => BitArrayListExpr::spread(
2386                elements.mapped_ref(|value| self.materialize_bit_array_value(value, substitution)),
2387                self.materialize_bit_array_list_value(tail, substitution),
2388            ),
2389            TypedConstantListValueKind::Reference(value) => {
2390                self.materialize_bit_array_list(&value.substitute_leaf(substitution))
2391            }
2392        }
2393    }
2394
2395    pub(crate) fn materialize_utf_codepoint_list(
2396        &self,
2397        value: &ConstantUtfCodepointListInstantiation,
2398    ) -> UtfCodepointListExpr {
2399        if !self.owns(value.module()) {
2400            return UtfCodepointListExpr::constant(
2401                ValueShape::UtfCodepoint,
2402                UtfCodepointListItem,
2403                value.clone(),
2404            );
2405        }
2406        match value.source() {
2407            ConstantListTemplateSource::Generic(source) => self
2408                .materialize_generic_utf_codepoint_list(
2409                    self.generic_list(*source),
2410                    value.substitution(),
2411                ),
2412            ConstantListTemplateSource::Exact(source) => self.materialize_utf_codepoint_list_value(
2413                self.utf_codepoint_list(*source),
2414                value.substitution(),
2415            ),
2416        }
2417    }
2418
2419    fn materialize_utf_codepoint_list_value(
2420        &self,
2421        value: &ConstantUtfCodepointListValue,
2422        substitution: &TypeSubstitution,
2423    ) -> UtfCodepointListExpr {
2424        match value.kind() {
2425            ConstantUtfCodepointListValueKind::Empty => {
2426                UtfCodepointListExpr::value(UtfCodepointListItem, Vec::new())
2427            }
2428            ConstantUtfCodepointListValueKind::Reference(value) => {
2429                self.materialize_utf_codepoint_list(&value.substitute_leaf(substitution))
2430            }
2431        }
2432    }
2433
2434    pub(crate) fn materialize_custom_list(
2435        &self,
2436        value: &ConstantCustomListInstantiation,
2437    ) -> CustomListExpr {
2438        if !self.owns(value.module()) {
2439            let shape = value.item_shape().clone();
2440            return CustomListExpr::constant(
2441                ValueShape::Custom(shape.clone()),
2442                CustomListItem::new(shape.type_().clone()),
2443                value.clone(),
2444            );
2445        }
2446        match value.source() {
2447            ConstantListTemplateSource::Generic(source) => self.materialize_generic_custom_list(
2448                self.generic_list(*source),
2449                value.substitution(),
2450                value.item_shape(),
2451            ),
2452            ConstantListTemplateSource::Exact(source) => {
2453                self.materialize_custom_list_value(self.custom_list(*source), value.substitution())
2454            }
2455        }
2456    }
2457
2458    fn materialize_custom_list_value(
2459        &self,
2460        value: &ConstantCustomListValue,
2461        substitution: &TypeSubstitution,
2462    ) -> CustomListExpr {
2463        let shape = value.item_shape().substitute(substitution);
2464        match value.kind() {
2465            TypedConstantListValueKind::Value(elements) => CustomListExpr::value(
2466                CustomListItem::new(shape.type_().clone()),
2467                elements
2468                    .iter()
2469                    .map(|value| self.materialize_custom_value(value, substitution))
2470                    .collect(),
2471            )
2472            .with_item_shape(ValueShape::Custom(shape)),
2473            TypedConstantListValueKind::Spread { elements, tail } => CustomListExpr::spread(
2474                elements.mapped_ref(|value| self.materialize_custom_value(value, substitution)),
2475                self.materialize_custom_list_value(tail, substitution),
2476            )
2477            .with_item_shape(ValueShape::Custom(shape)),
2478            TypedConstantListValueKind::Reference(value) => {
2479                self.materialize_custom_list(&value.substitute_custom(substitution))
2480            }
2481        }
2482    }
2483
2484    pub(crate) fn materialize_external_list(
2485        &self,
2486        value: &ConstantExternalListInstantiation,
2487    ) -> ExternalListExpr {
2488        if !self.owns(value.module()) {
2489            let shape = value.item_shape().clone();
2490            return ExternalListExpr::constant(
2491                ValueShape::External(shape.clone()),
2492                ExternalListItem::new(shape.type_().clone()),
2493                value.clone(),
2494            );
2495        }
2496        match value.source() {
2497            ConstantListTemplateSource::Generic(source) => self.materialize_generic_external_list(
2498                self.generic_list(*source),
2499                value.substitution(),
2500                value.item_shape(),
2501            ),
2502            ConstantListTemplateSource::Exact(source) => self
2503                .materialize_external_list_value(self.external_list(*source), value.substitution()),
2504        }
2505    }
2506
2507    fn materialize_external_list_value(
2508        &self,
2509        value: &ConstantExternalListValue,
2510        substitution: &TypeSubstitution,
2511    ) -> ExternalListExpr {
2512        let shape = value.item_shape().substitute(substitution);
2513        match value.kind() {
2514            ConstantExternalListValueKind::Empty => {
2515                ExternalListExpr::value(ExternalListItem::new(shape.type_().clone()), Vec::new())
2516                    .with_item_shape(ValueShape::External(shape))
2517            }
2518            ConstantExternalListValueKind::Reference(value) => {
2519                self.materialize_external_list(&value.substitute_external(substitution))
2520            }
2521        }
2522    }
2523
2524    pub(crate) fn materialize_float_list(
2525        &self,
2526        value: &ConstantFloatListInstantiation,
2527    ) -> FloatListExpr {
2528        if !self.owns(value.module()) {
2529            return FloatListExpr::constant(ValueShape::Float, FloatListItem, value.clone());
2530        }
2531        match value.source() {
2532            ConstantListTemplateSource::Generic(source) => self
2533                .materialize_generic_float_list(self.generic_list(*source), value.substitution()),
2534            ConstantListTemplateSource::Exact(source) => {
2535                self.materialize_float_list_value(self.float_list(*source), value.substitution())
2536            }
2537        }
2538    }
2539
2540    fn materialize_float_list_value(
2541        &self,
2542        value: &ConstantFloatListValue,
2543        substitution: &TypeSubstitution,
2544    ) -> FloatListExpr {
2545        match value.kind() {
2546            TypedConstantListValueKind::Value(elements) => FloatListExpr::value(
2547                FloatListItem,
2548                elements
2549                    .iter()
2550                    .map(|value| self.materialize_float_value(value, substitution))
2551                    .collect(),
2552            ),
2553            TypedConstantListValueKind::Spread { elements, tail } => FloatListExpr::spread(
2554                elements.mapped_ref(|value| self.materialize_float_value(value, substitution)),
2555                self.materialize_float_list_value(tail, substitution),
2556            ),
2557            TypedConstantListValueKind::Reference(value) => {
2558                self.materialize_float_list(&value.substitute_leaf(substitution))
2559            }
2560        }
2561    }
2562
2563    pub(crate) fn materialize_bool_list(
2564        &self,
2565        value: &ConstantBoolListInstantiation,
2566    ) -> BoolListExpr {
2567        if !self.owns(value.module()) {
2568            return BoolListExpr::constant(ValueShape::Bool, BoolListItem, value.clone());
2569        }
2570        match value.source() {
2571            ConstantListTemplateSource::Generic(source) => {
2572                self.materialize_generic_bool_list(self.generic_list(*source), value.substitution())
2573            }
2574            ConstantListTemplateSource::Exact(source) => {
2575                self.materialize_bool_list_value(self.bool_list(*source), value.substitution())
2576            }
2577        }
2578    }
2579
2580    fn materialize_bool_list_value(
2581        &self,
2582        value: &ConstantBoolListValue,
2583        substitution: &TypeSubstitution,
2584    ) -> BoolListExpr {
2585        match value.kind() {
2586            TypedConstantListValueKind::Value(elements) => BoolListExpr::value(
2587                BoolListItem,
2588                elements
2589                    .iter()
2590                    .map(|value| self.materialize_bool_value(value, substitution))
2591                    .collect(),
2592            ),
2593            TypedConstantListValueKind::Spread { elements, tail } => BoolListExpr::spread(
2594                elements.mapped_ref(|value| self.materialize_bool_value(value, substitution)),
2595                self.materialize_bool_list_value(tail, substitution),
2596            ),
2597            TypedConstantListValueKind::Reference(value) => {
2598                self.materialize_bool_list(&value.substitute_leaf(substitution))
2599            }
2600        }
2601    }
2602
2603    pub(crate) fn materialize_nil_list(&self, value: &ConstantNilListInstantiation) -> NilListExpr {
2604        if !self.owns(value.module()) {
2605            return NilListExpr::constant(ValueShape::Nil, NilListItem, value.clone());
2606        }
2607        match value.source() {
2608            ConstantListTemplateSource::Generic(source) => {
2609                self.materialize_generic_nil_list(self.generic_list(*source), value.substitution())
2610            }
2611            ConstantListTemplateSource::Exact(source) => {
2612                self.materialize_nil_list_value(self.nil_list(*source), value.substitution())
2613            }
2614        }
2615    }
2616
2617    fn materialize_nil_list_value(
2618        &self,
2619        value: &ConstantNilListValue,
2620        substitution: &TypeSubstitution,
2621    ) -> NilListExpr {
2622        match value.kind() {
2623            TypedConstantListValueKind::Value(elements) => NilListExpr::value(
2624                NilListItem,
2625                elements
2626                    .iter()
2627                    .map(|value| self.materialize_nil_value(value, substitution))
2628                    .collect(),
2629            ),
2630            TypedConstantListValueKind::Spread { elements, tail } => NilListExpr::spread(
2631                elements.mapped_ref(|value| self.materialize_nil_value(value, substitution)),
2632                self.materialize_nil_list_value(tail, substitution),
2633            ),
2634            TypedConstantListValueKind::Reference(value) => {
2635                self.materialize_nil_list(&value.substitute_leaf(substitution))
2636            }
2637        }
2638    }
2639
2640    pub(crate) fn materialize_tuple_list(
2641        &self,
2642        value: &ConstantTupleListInstantiation,
2643    ) -> TupleListExpr {
2644        if !self.owns(value.module()) {
2645            let shape = value.item_shape().clone();
2646            return TupleListExpr::constant(
2647                ValueShape::Tuple(shape.clone()),
2648                TupleListItem::new(shape.iter().map(ValueShape::value_type).collect()),
2649                value.clone(),
2650            );
2651        }
2652        match value.source() {
2653            ConstantListTemplateSource::Generic(source) => self.materialize_generic_tuple_list(
2654                self.generic_list(*source),
2655                value.substitution(),
2656                value.item_shape(),
2657            ),
2658            ConstantListTemplateSource::Exact(source) => {
2659                self.materialize_tuple_list_value(self.tuple_list(*source), value.substitution())
2660            }
2661        }
2662    }
2663
2664    fn materialize_tuple_list_value(
2665        &self,
2666        value: &ConstantTupleListValue,
2667        substitution: &TypeSubstitution,
2668    ) -> TupleListExpr {
2669        let shape = value
2670            .item_shape()
2671            .iter()
2672            .map(|shape| shape.substitute(substitution))
2673            .collect::<Vec<_>>()
2674            .into_boxed_slice();
2675        let item = TupleListItem::new(shape.iter().map(ValueShape::value_type).collect());
2676        match value.kind() {
2677            TypedConstantListValueKind::Value(elements) => TupleListExpr::value(
2678                item,
2679                elements
2680                    .iter()
2681                    .map(|value| self.materialize_tuple_value(value, substitution))
2682                    .collect(),
2683            )
2684            .with_item_shape(ValueShape::Tuple(shape)),
2685            TypedConstantListValueKind::Spread { elements, tail } => TupleListExpr::spread(
2686                elements.mapped_ref(|value| self.materialize_tuple_value(value, substitution)),
2687                self.materialize_tuple_list_value(tail, substitution),
2688            )
2689            .with_item_shape(ValueShape::Tuple(shape)),
2690            TypedConstantListValueKind::Reference(value) => {
2691                self.materialize_tuple_list(&value.substitute_tuple(substitution))
2692            }
2693        }
2694    }
2695
2696    pub(crate) fn materialize_parameter_list_list(
2697        &self,
2698        value: &ConstantParameterListListInstantiation,
2699    ) -> ParameterListListExpr {
2700        if !self.owns(value.module()) {
2701            let parameter = *value.item_shape();
2702            return ParameterListListExpr::constant(
2703                ValueShape::List(Box::new(ValueShape::Parameter(parameter))),
2704                ParameterListListItem::new(parameter),
2705                value.clone(),
2706            );
2707        }
2708        match value.source() {
2709            ConstantListTemplateSource::Generic(source) => self
2710                .materialize_generic_parameter_list_list(
2711                    self.generic_list(*source),
2712                    value.substitution(),
2713                    *value.item_shape(),
2714                ),
2715            ConstantListTemplateSource::Exact(source) => self
2716                .materialize_parameter_list_list_value(
2717                    self.parameter_list_list(*source),
2718                    value.substitution(),
2719                    *value.item_shape(),
2720                ),
2721        }
2722    }
2723
2724    fn materialize_parameter_list_list_value(
2725        &self,
2726        value: &ConstantParameterListListValue,
2727        substitution: &TypeSubstitution,
2728        parameter: crate::plan::TypeParameterId,
2729    ) -> ParameterListListExpr {
2730        match value.kind() {
2731            TypedConstantListValueKind::Value(elements) => ParameterListListExpr::value(
2732                ParameterListListItem::new(parameter),
2733                elements
2734                    .iter()
2735                    .map(|value| {
2736                        self.materialize_generic_parameter_list(value, substitution, parameter)
2737                    })
2738                    .collect(),
2739            )
2740            .with_item_shape(ValueShape::List(Box::new(ValueShape::Parameter(parameter)))),
2741            TypedConstantListValueKind::Spread { elements, tail } => ParameterListListExpr::spread(
2742                elements.mapped_ref(|value| {
2743                    self.materialize_generic_parameter_list(value, substitution, parameter)
2744                }),
2745                self.materialize_parameter_list_list_value(tail, substitution, parameter),
2746            )
2747            .with_item_shape(ValueShape::List(Box::new(ValueShape::Parameter(parameter)))),
2748            TypedConstantListValueKind::Reference(value) => self.materialize_parameter_list_list(
2749                &value.retarget_parameter(substitution, parameter),
2750            ),
2751        }
2752    }
2753
2754    fn materialize_parameter_list_list_value_as_stored(
2755        &self,
2756        value: &ConstantParameterListListValue,
2757        substitution: &TypeSubstitution,
2758        shape: &crate::plan::ValueStorageShape,
2759    ) -> ListListExpr {
2760        match value.kind() {
2761            TypedConstantListValueKind::Value(elements) => ListListExpr::value(
2762                ListListItem::new(shape.clone()),
2763                elements
2764                    .iter()
2765                    .map(|value| {
2766                        self.materialize_generic_stored_list_value(value, substitution, shape)
2767                    })
2768                    .collect(),
2769            )
2770            .with_item_shape(ValueShape::List(Box::new(shape.to_value_shape()))),
2771            TypedConstantListValueKind::Spread { elements, tail } => ListListExpr::spread(
2772                elements.mapped_ref(|value| {
2773                    self.materialize_generic_stored_list_value(value, substitution, shape)
2774                }),
2775                self.materialize_parameter_list_list_value_as_stored(tail, substitution, shape),
2776            )
2777            .with_item_shape(ValueShape::List(Box::new(shape.to_value_shape()))),
2778            TypedConstantListValueKind::Reference(value) => {
2779                self.materialize_list_list(&value.retarget_stored(substitution, shape.clone()))
2780            }
2781        }
2782    }
2783
2784    fn materialize_stored_list_value(
2785        &self,
2786        value: &ConstantStoredListValue,
2787        substitution: &TypeSubstitution,
2788    ) -> StoredListExpr {
2789        match value {
2790            ConstantStoredListValue::ParameterList(value) => {
2791                match ValueShape::Parameter(*value.item_shape())
2792                    .substitute(substitution)
2793                    .representation()
2794                {
2795                    crate::plan::ValueRepresentation::Uninhabited(parameter) => {
2796                        StoredListExpr::ParameterList(self.materialize_parameter_list_list_value(
2797                            value,
2798                            substitution,
2799                            parameter,
2800                        ))
2801                    }
2802                    crate::plan::ValueRepresentation::Stored(shape) => {
2803                        StoredListExpr::List(self.materialize_parameter_list_list_value_as_stored(
2804                            value,
2805                            substitution,
2806                            &shape,
2807                        ))
2808                    }
2809                }
2810            }
2811            ConstantStoredListValue::Int(value) => {
2812                StoredListExpr::Int(self.materialize_int_list_value(value, substitution))
2813            }
2814            ConstantStoredListValue::String(value) => {
2815                StoredListExpr::String(self.materialize_string_list_value(value, substitution))
2816            }
2817            ConstantStoredListValue::BitArray(value) => {
2818                StoredListExpr::BitArray(self.materialize_bit_array_list_value(value, substitution))
2819            }
2820            ConstantStoredListValue::UtfCodepoint(value) => StoredListExpr::UtfCodepoint(
2821                self.materialize_utf_codepoint_list_value(value, substitution),
2822            ),
2823            ConstantStoredListValue::Custom(value) => {
2824                StoredListExpr::Custom(self.materialize_custom_list_value(value, substitution))
2825            }
2826            ConstantStoredListValue::External(value) => {
2827                StoredListExpr::External(self.materialize_external_list_value(value, substitution))
2828            }
2829            ConstantStoredListValue::Float(value) => {
2830                StoredListExpr::Float(self.materialize_float_list_value(value, substitution))
2831            }
2832            ConstantStoredListValue::Bool(value) => {
2833                StoredListExpr::Bool(self.materialize_bool_list_value(value, substitution))
2834            }
2835            ConstantStoredListValue::Nil(value) => {
2836                StoredListExpr::Nil(self.materialize_nil_list_value(value, substitution))
2837            }
2838            ConstantStoredListValue::Tuple(value) => {
2839                StoredListExpr::Tuple(self.materialize_tuple_list_value(value, substitution))
2840            }
2841            ConstantStoredListValue::List(value) => {
2842                StoredListExpr::List(self.materialize_list_list_value(value, substitution))
2843            }
2844            ConstantStoredListValue::Function(value) => {
2845                StoredListExpr::Function(self.materialize_function_list_value(value, substitution))
2846            }
2847        }
2848    }
2849
2850    pub(crate) fn materialize_list_list(
2851        &self,
2852        value: &ConstantListListInstantiation,
2853    ) -> ListListExpr {
2854        if !self.owns(value.module()) {
2855            let shape = value.item_shape().clone();
2856            return ListListExpr::constant(
2857                ValueShape::List(Box::new(shape.to_value_shape())),
2858                ListListItem::new(shape),
2859                value.clone(),
2860            );
2861        }
2862        match value.source() {
2863            ConstantNestedListTemplateSource::Generic(source) => self
2864                .materialize_generic_list_list(
2865                    self.generic_list(*source),
2866                    value.substitution(),
2867                    value.item_shape(),
2868                ),
2869            ConstantNestedListTemplateSource::ParameterList(source) => self
2870                .materialize_parameter_list_list_value_as_stored(
2871                    self.parameter_list_list(*source),
2872                    value.substitution(),
2873                    value.item_shape(),
2874                ),
2875            ConstantNestedListTemplateSource::Exact(source) => {
2876                self.materialize_list_list_value(self.list_list(*source), value.substitution())
2877            }
2878        }
2879    }
2880
2881    fn materialize_list_list_value(
2882        &self,
2883        value: &ConstantListListValue,
2884        substitution: &TypeSubstitution,
2885    ) -> ListListExpr {
2886        let shape = value.item_shape().substitute(substitution);
2887        match value.kind() {
2888            TypedConstantListValueKind::Value(elements) => ListListExpr::value(
2889                ListListItem::new(shape.clone()),
2890                elements
2891                    .iter()
2892                    .map(|value| self.materialize_stored_list_value(value, substitution))
2893                    .collect(),
2894            )
2895            .with_item_shape(ValueShape::List(Box::new(shape.to_value_shape()))),
2896            TypedConstantListValueKind::Spread { elements, tail } => ListListExpr::spread(
2897                elements
2898                    .mapped_ref(|value| self.materialize_stored_list_value(value, substitution)),
2899                self.materialize_list_list_value(tail, substitution),
2900            )
2901            .with_item_shape(ValueShape::List(Box::new(shape.to_value_shape()))),
2902            TypedConstantListValueKind::Reference(value) => {
2903                self.materialize_list_list(&value.substitute_list(substitution))
2904            }
2905        }
2906    }
2907
2908    pub(crate) fn materialize_function_list(
2909        &self,
2910        value: &ConstantFunctionListInstantiation,
2911    ) -> FunctionListExpr {
2912        if !self.owns(value.module()) {
2913            let shape = value.item_shape().clone();
2914            return FunctionListExpr::constant(
2915                ValueShape::Function(Box::new(shape.clone())),
2916                FunctionListItem::new(shape.type_()),
2917                value.clone(),
2918            );
2919        }
2920        match value.source() {
2921            ConstantListTemplateSource::Generic(source) => self.materialize_generic_function_list(
2922                self.generic_list(*source),
2923                value.substitution(),
2924                value.item_shape(),
2925            ),
2926            ConstantListTemplateSource::Exact(source) => self
2927                .materialize_function_list_value(self.function_list(*source), value.substitution()),
2928        }
2929    }
2930
2931    fn materialize_function_list_value(
2932        &self,
2933        value: &ConstantFunctionListValue,
2934        substitution: &TypeSubstitution,
2935    ) -> FunctionListExpr {
2936        let shape = value.item_shape().substitute(substitution);
2937        match value.kind() {
2938            TypedConstantListValueKind::Value(elements) => FunctionListExpr::value(
2939                FunctionListItem::new(shape.type_()),
2940                elements
2941                    .iter()
2942                    .map(|value| self.materialize_function_value(value, substitution))
2943                    .collect(),
2944            )
2945            .with_item_shape(ValueShape::Function(Box::new(shape))),
2946            TypedConstantListValueKind::Spread { elements, tail } => FunctionListExpr::spread(
2947                elements.mapped_ref(|value| self.materialize_function_value(value, substitution)),
2948                self.materialize_function_list_value(tail, substitution),
2949            )
2950            .with_item_shape(ValueShape::Function(Box::new(shape))),
2951            TypedConstantListValueKind::Reference(value) => {
2952                self.materialize_function_list(&value.substitute_function(substitution))
2953            }
2954        }
2955    }
2956}
2957
2958impl ConstantTemplateSignature {
2959    pub(crate) fn int(id: ConstantTemplateId, storage_index: usize, scheme: TypeScheme) -> Self {
2960        Self::new(
2961            id,
2962            scheme,
2963            ValueShape::Int,
2964            ConstantTemplateSignatureKind::Int(ConstantIntTemplateId(storage_index)),
2965        )
2966    }
2967
2968    pub(crate) fn string(id: ConstantTemplateId, storage_index: usize, scheme: TypeScheme) -> Self {
2969        Self::new(
2970            id,
2971            scheme,
2972            ValueShape::String,
2973            ConstantTemplateSignatureKind::String(ConstantStringTemplateId(storage_index)),
2974        )
2975    }
2976
2977    pub(crate) fn bit_array(
2978        id: ConstantTemplateId,
2979        storage_index: usize,
2980        scheme: TypeScheme,
2981    ) -> Self {
2982        Self::new(
2983            id,
2984            scheme,
2985            ValueShape::BitArray,
2986            ConstantTemplateSignatureKind::BitArray(ConstantBitArrayTemplateId(storage_index)),
2987        )
2988    }
2989
2990    pub(crate) fn custom(
2991        id: ConstantTemplateId,
2992        storage_index: usize,
2993        scheme: TypeScheme,
2994        shape: CustomValueShape,
2995    ) -> Self {
2996        let kind_shape = shape.clone();
2997        Self::new(
2998            id,
2999            scheme,
3000            ValueShape::Custom(shape),
3001            ConstantTemplateSignatureKind::Custom {
3002                template: ConstantCustomTemplateId(storage_index),
3003                shape: kind_shape,
3004            },
3005        )
3006    }
3007
3008    pub(crate) fn float(id: ConstantTemplateId, storage_index: usize, scheme: TypeScheme) -> Self {
3009        Self::new(
3010            id,
3011            scheme,
3012            ValueShape::Float,
3013            ConstantTemplateSignatureKind::Float(ConstantFloatTemplateId(storage_index)),
3014        )
3015    }
3016
3017    pub(crate) fn bool(id: ConstantTemplateId, storage_index: usize, scheme: TypeScheme) -> Self {
3018        Self::new(
3019            id,
3020            scheme,
3021            ValueShape::Bool,
3022            ConstantTemplateSignatureKind::Bool(ConstantBoolTemplateId(storage_index)),
3023        )
3024    }
3025
3026    pub(crate) fn nil(id: ConstantTemplateId, storage_index: usize, scheme: TypeScheme) -> Self {
3027        Self::new(
3028            id,
3029            scheme,
3030            ValueShape::Nil,
3031            ConstantTemplateSignatureKind::Nil(ConstantNilTemplateId(storage_index)),
3032        )
3033    }
3034
3035    pub(crate) fn tuple(
3036        id: ConstantTemplateId,
3037        storage_index: usize,
3038        scheme: TypeScheme,
3039        shape: Box<[ValueShape]>,
3040    ) -> Self {
3041        let kind_shape = shape.clone();
3042        Self::new(
3043            id,
3044            scheme,
3045            ValueShape::Tuple(shape),
3046            ConstantTemplateSignatureKind::Tuple {
3047                template: ConstantTupleTemplateId(storage_index),
3048                shape: kind_shape,
3049            },
3050        )
3051    }
3052
3053    pub(crate) fn list(
3054        id: ConstantTemplateId,
3055        storage_index: usize,
3056        scheme: TypeScheme,
3057        item_shape: ValueShape,
3058    ) -> Self {
3059        let template = ConstantListTemplate::from_item_shape(item_shape, storage_index);
3060        let item_shape = template.item_shape();
3061        Self::new(
3062            id,
3063            scheme,
3064            ValueShape::List(Box::new(item_shape)),
3065            ConstantTemplateSignatureKind::List(template),
3066        )
3067    }
3068
3069    pub(crate) fn function(
3070        id: ConstantTemplateId,
3071        storage_index: usize,
3072        scheme: TypeScheme,
3073        shape: FunctionShape,
3074    ) -> Self {
3075        let template = ConstantFunctionTemplate::from_shape(&shape, storage_index);
3076        let kind_shape = shape.clone();
3077        Self::new(
3078            id,
3079            scheme,
3080            ValueShape::Function(Box::new(shape)),
3081            ConstantTemplateSignatureKind::Function {
3082                template,
3083                shape: kind_shape,
3084            },
3085        )
3086    }
3087
3088    fn new(
3089        id: ConstantTemplateId,
3090        scheme: TypeScheme,
3091        shape: ValueShape,
3092        kind: ConstantTemplateSignatureKind,
3093    ) -> Self {
3094        Self {
3095            id,
3096            scheme,
3097            shape,
3098            kind,
3099        }
3100    }
3101
3102    pub(crate) fn id(&self) -> ConstantTemplateId {
3103        self.id
3104    }
3105
3106    pub(crate) fn scheme(&self) -> &TypeScheme {
3107        &self.scheme
3108    }
3109
3110    pub(crate) fn shape(&self) -> &ValueShape {
3111        &self.shape
3112    }
3113
3114    pub(crate) fn try_instantiate(
3115        &self,
3116        arguments: Vec<ValueShape>,
3117    ) -> Option<ConstantInstantiation> {
3118        let substitution = self.scheme.try_substitution(arguments)?;
3119        let kind = match &self.kind {
3120            ConstantTemplateSignatureKind::Int(template) => {
3121                ConstantInstantiationKind::Int(TypedConstantInstantiation::in_module(
3122                    self.id.module(),
3123                    *template,
3124                    substitution,
3125                    (),
3126                ))
3127            }
3128            ConstantTemplateSignatureKind::String(template) => {
3129                ConstantInstantiationKind::String(TypedConstantInstantiation::in_module(
3130                    self.id.module(),
3131                    *template,
3132                    substitution,
3133                    (),
3134                ))
3135            }
3136            ConstantTemplateSignatureKind::BitArray(template) => {
3137                ConstantInstantiationKind::BitArray(TypedConstantInstantiation::in_module(
3138                    self.id.module(),
3139                    *template,
3140                    substitution,
3141                    (),
3142                ))
3143            }
3144            ConstantTemplateSignatureKind::Custom { template, shape } => {
3145                let shape = shape.substitute(&substitution);
3146                ConstantInstantiationKind::Custom(TypedConstantInstantiation::in_module(
3147                    self.id.module(),
3148                    *template,
3149                    substitution,
3150                    shape,
3151                ))
3152            }
3153            ConstantTemplateSignatureKind::Float(template) => {
3154                ConstantInstantiationKind::Float(TypedConstantInstantiation::in_module(
3155                    self.id.module(),
3156                    *template,
3157                    substitution,
3158                    (),
3159                ))
3160            }
3161            ConstantTemplateSignatureKind::Bool(template) => {
3162                ConstantInstantiationKind::Bool(TypedConstantInstantiation::in_module(
3163                    self.id.module(),
3164                    *template,
3165                    substitution,
3166                    (),
3167                ))
3168            }
3169            ConstantTemplateSignatureKind::Nil(template) => {
3170                ConstantInstantiationKind::Nil(TypedConstantInstantiation::in_module(
3171                    self.id.module(),
3172                    *template,
3173                    substitution,
3174                    (),
3175                ))
3176            }
3177            ConstantTemplateSignatureKind::Tuple { template, shape } => {
3178                let shape = shape
3179                    .iter()
3180                    .map(|shape| shape.substitute(&substitution))
3181                    .collect::<Vec<_>>()
3182                    .into_boxed_slice();
3183                ConstantInstantiationKind::Tuple(TypedConstantInstantiation::in_module(
3184                    self.id.module(),
3185                    *template,
3186                    substitution,
3187                    shape,
3188                ))
3189            }
3190            ConstantTemplateSignatureKind::List(template) => ConstantInstantiationKind::List(
3191                template.instantiate(self.id.module(), substitution),
3192            ),
3193            ConstantTemplateSignatureKind::Function { template, shape } => {
3194                let shape = shape.substitute(&substitution);
3195                ConstantInstantiationKind::Function(template.instantiate(
3196                    self.id.module(),
3197                    substitution,
3198                    shape,
3199                ))
3200            }
3201        };
3202        Some(ConstantInstantiation { kind })
3203    }
3204}
3205
3206impl<Id: Copy, Shape> TypedConstantInstantiation<Id, Shape> {
3207    #[cfg(test)]
3208    fn new(template: Id, substitution: TypeSubstitution, shape: Shape) -> Self {
3209        Self::in_module(crate::plan::ModuleId::root(), template, substitution, shape)
3210    }
3211
3212    fn in_module(
3213        module: crate::plan::ModuleId,
3214        template: Id,
3215        substitution: TypeSubstitution,
3216        shape: Shape,
3217    ) -> Self {
3218        Self {
3219            module,
3220            template,
3221            substitution,
3222            shape,
3223        }
3224    }
3225
3226    pub(crate) fn template(&self) -> Id {
3227        self.template
3228    }
3229
3230    pub(crate) fn module(&self) -> crate::plan::ModuleId {
3231        self.module
3232    }
3233
3234    pub(crate) fn substitution(&self) -> &TypeSubstitution {
3235        &self.substitution
3236    }
3237
3238    pub(crate) fn shape(&self) -> &Shape {
3239        &self.shape
3240    }
3241}
3242
3243impl<Id: Copy> TypedConstantInstantiation<Id, ()> {
3244    fn substitute_leaf(&self, outer: &TypeSubstitution) -> Self {
3245        Self::in_module(
3246            self.module,
3247            self.template,
3248            self.substitution.substitute(outer),
3249            (),
3250        )
3251    }
3252}
3253
3254impl TypedConstantInstantiation<ConstantCustomTemplateId, CustomValueShape> {
3255    fn substitute_custom(&self, outer: &TypeSubstitution) -> Self {
3256        Self::in_module(
3257            self.module,
3258            self.template,
3259            self.substitution.substitute(outer),
3260            self.shape.substitute(outer),
3261        )
3262    }
3263}
3264
3265impl TypedConstantInstantiation<ConstantTupleTemplateId, Box<[ValueShape]>> {
3266    fn substitute_tuple(&self, outer: &TypeSubstitution) -> Self {
3267        Self::in_module(
3268            self.module,
3269            self.template,
3270            self.substitution.substitute(outer),
3271            self.shape
3272                .iter()
3273                .map(|shape| shape.substitute(outer))
3274                .collect::<Vec<_>>()
3275                .into_boxed_slice(),
3276        )
3277    }
3278}
3279
3280impl ConstantValue {
3281    pub(crate) fn int(value: BigInt) -> Self {
3282        Self {
3283            kind: ConstantValueKind::Int(ConstantIntValue::Value(value)),
3284        }
3285    }
3286
3287    pub(crate) fn float(value: f64) -> Self {
3288        Self {
3289            kind: ConstantValueKind::Float(ConstantFloatValue::Value(value)),
3290        }
3291    }
3292
3293    pub(crate) fn string(value: EcoString) -> Self {
3294        Self {
3295            kind: ConstantValueKind::String(ConstantStringValue::Value(value)),
3296        }
3297    }
3298
3299    pub(crate) fn string_concatenation(
3300        left: ConstantStringValue,
3301        right: ConstantStringValue,
3302    ) -> Self {
3303        Self {
3304            kind: ConstantValueKind::String(ConstantStringValue::Concatenation {
3305                left: Box::new(left),
3306                right: Box::new(right),
3307            }),
3308        }
3309    }
3310
3311    pub(crate) fn bool(value: bool) -> Self {
3312        Self {
3313            kind: ConstantValueKind::Bool(ConstantBoolValue::Value(value)),
3314        }
3315    }
3316
3317    pub(crate) fn nil() -> Self {
3318        Self {
3319            kind: ConstantValueKind::Nil(ConstantNilValue::Value),
3320        }
3321    }
3322
3323    pub(crate) fn tuple(element_shapes: Box<[ValueShape]>, elements: Box<[Self]>) -> Self {
3324        Self {
3325            kind: ConstantValueKind::Tuple(ConstantTupleValue {
3326                shape: element_shapes,
3327                kind: ConstantTupleValueKind::Value(elements),
3328            }),
3329        }
3330    }
3331
3332    pub(crate) fn try_list(
3333        item_shape: ValueShape,
3334        elements: Vec<Self>,
3335        tail: Option<Self>,
3336    ) -> Result<Self, ConstantListConstructionError> {
3337        let tail = tail
3338            .map(|tail| {
3339                let actual = tail.shape();
3340                match tail.into_list() {
3341                    Some(tail) => Ok(tail),
3342                    None => Err(constant_list_tail_mismatch(&item_shape, actual)),
3343                }
3344            })
3345            .transpose()?;
3346        let parts = ConstantListParts::try_from_parts(elements, tail)?;
3347
3348        let value = match &item_shape {
3349            ValueShape::Parameter(parameter) => {
3350                match parts {
3351                    ConstantListParts::Value(elements) if elements.is_empty() => {}
3352                    ConstantListParts::Value(elements) => {
3353                        return Err(constant_list_element_mismatch(
3354                            &item_shape,
3355                            elements[0].shape(),
3356                        ));
3357                    }
3358                    ConstantListParts::Spread { elements, .. } => {
3359                        return Err(constant_list_element_mismatch(
3360                            &item_shape,
3361                            elements.first().shape(),
3362                        ));
3363                    }
3364                }
3365                ConstantListValue::generic(*parameter)
3366            }
3367            ValueShape::Int => ConstantListValue::int(parts.try_map(
3368                |value| {
3369                    let actual = value.shape();
3370                    match value.into_int() {
3371                        Some(value) => Ok(value),
3372                        None => Err(constant_list_element_mismatch(&item_shape, actual)),
3373                    }
3374                },
3375                |tail| {
3376                    let actual = tail.shape();
3377                    match tail.into_int() {
3378                        Some(tail) => Ok(tail),
3379                        None => Err(constant_list_tail_mismatch(&item_shape, actual)),
3380                    }
3381                },
3382            )?),
3383            ValueShape::String => ConstantListValue::string(parts.try_map(
3384                |value| {
3385                    let actual = value.shape();
3386                    match value.into_string() {
3387                        Some(value) => Ok(value),
3388                        None => Err(constant_list_element_mismatch(&item_shape, actual)),
3389                    }
3390                },
3391                |tail| {
3392                    let actual = tail.shape();
3393                    match tail.into_string() {
3394                        Some(tail) => Ok(tail),
3395                        None => Err(constant_list_tail_mismatch(&item_shape, actual)),
3396                    }
3397                },
3398            )?),
3399            ValueShape::BitArray => ConstantListValue::bit_array(parts.try_map(
3400                |value| {
3401                    let actual = value.shape();
3402                    match value.into_bit_array() {
3403                        Some(value) => Ok(value),
3404                        None => Err(constant_list_element_mismatch(&item_shape, actual)),
3405                    }
3406                },
3407                |tail| {
3408                    let actual = tail.shape();
3409                    match tail.into_bit_array() {
3410                        Some(tail) => Ok(tail),
3411                        None => Err(constant_list_tail_mismatch(&item_shape, actual)),
3412                    }
3413                },
3414            )?),
3415            ValueShape::UtfCodepoint => {
3416                match parts {
3417                    ConstantListParts::Value(elements) if elements.is_empty() => {}
3418                    ConstantListParts::Value(elements) => {
3419                        return Err(constant_list_element_mismatch(
3420                            &item_shape,
3421                            elements[0].shape(),
3422                        ));
3423                    }
3424                    ConstantListParts::Spread { elements, .. } => {
3425                        return Err(constant_list_element_mismatch(
3426                            &item_shape,
3427                            elements.first().shape(),
3428                        ));
3429                    }
3430                }
3431                ConstantListValue::utf_codepoint()
3432            }
3433            ValueShape::Custom(shape) => ConstantListValue::custom(
3434                shape.clone(),
3435                parts.try_map(
3436                    |value| {
3437                        let actual = value.shape();
3438                        match value.kind {
3439                            ConstantValueKind::Custom(value) if actual.can_flow_to(&item_shape) => {
3440                                Ok(value)
3441                            }
3442                            _ => Err(constant_list_element_mismatch(&item_shape, actual)),
3443                        }
3444                    },
3445                    |tail| {
3446                        let actual = tail.shape();
3447                        match tail {
3448                            ConstantListValue::Custom(value)
3449                                if actual.can_flow_to(&ValueShape::List(Box::new(
3450                                    item_shape.clone(),
3451                                ))) =>
3452                            {
3453                                Ok(value)
3454                            }
3455                            _ => Err(constant_list_tail_mismatch(&item_shape, actual)),
3456                        }
3457                    },
3458                )?,
3459            ),
3460            ValueShape::External(shape) => {
3461                match parts {
3462                    ConstantListParts::Value(elements) if elements.is_empty() => {}
3463                    ConstantListParts::Value(elements) => {
3464                        return Err(constant_list_element_mismatch(
3465                            &item_shape,
3466                            elements[0].shape(),
3467                        ));
3468                    }
3469                    ConstantListParts::Spread { elements, .. } => {
3470                        return Err(constant_list_element_mismatch(
3471                            &item_shape,
3472                            elements.first().shape(),
3473                        ));
3474                    }
3475                }
3476                ConstantListValue::external(shape.clone())
3477            }
3478            ValueShape::Float => ConstantListValue::float(parts.try_map(
3479                |value| {
3480                    let actual = value.shape();
3481                    match value.into_float() {
3482                        Some(value) => Ok(value),
3483                        None => Err(constant_list_element_mismatch(&item_shape, actual)),
3484                    }
3485                },
3486                |tail| {
3487                    let actual = tail.shape();
3488                    match tail.into_float() {
3489                        Some(tail) => Ok(tail),
3490                        None => Err(constant_list_tail_mismatch(&item_shape, actual)),
3491                    }
3492                },
3493            )?),
3494            ValueShape::Bool => ConstantListValue::bool(parts.try_map(
3495                |value| {
3496                    let actual = value.shape();
3497                    match value.into_bool() {
3498                        Some(value) => Ok(value),
3499                        None => Err(constant_list_element_mismatch(&item_shape, actual)),
3500                    }
3501                },
3502                |tail| {
3503                    let actual = tail.shape();
3504                    match tail.into_bool() {
3505                        Some(tail) => Ok(tail),
3506                        None => Err(constant_list_tail_mismatch(&item_shape, actual)),
3507                    }
3508                },
3509            )?),
3510            ValueShape::Nil => ConstantListValue::nil(parts.try_map(
3511                |value| {
3512                    let actual = value.shape();
3513                    match value.into_nil() {
3514                        Some(value) => Ok(value),
3515                        None => Err(constant_list_element_mismatch(&item_shape, actual)),
3516                    }
3517                },
3518                |tail| {
3519                    let actual = tail.shape();
3520                    match tail.into_nil() {
3521                        Some(tail) => Ok(tail),
3522                        None => Err(constant_list_tail_mismatch(&item_shape, actual)),
3523                    }
3524                },
3525            )?),
3526            ValueShape::Tuple(shape) => ConstantListValue::tuple(
3527                shape.clone(),
3528                parts.try_map(
3529                    |value| {
3530                        let actual = value.shape();
3531                        match value.kind {
3532                            ConstantValueKind::Tuple(value) if actual.can_flow_to(&item_shape) => {
3533                                Ok(value)
3534                            }
3535                            _ => Err(constant_list_element_mismatch(&item_shape, actual)),
3536                        }
3537                    },
3538                    |tail| {
3539                        let actual = tail.shape();
3540                        match tail {
3541                            ConstantListValue::Tuple(value)
3542                                if actual.can_flow_to(&ValueShape::List(Box::new(
3543                                    item_shape.clone(),
3544                                ))) =>
3545                            {
3546                                Ok(value)
3547                            }
3548                            _ => Err(constant_list_tail_mismatch(&item_shape, actual)),
3549                        }
3550                    },
3551                )?,
3552            ),
3553            ValueShape::List(shape) => match shape.representation() {
3554                crate::plan::ValueRepresentation::Uninhabited(parameter) => {
3555                    ConstantListValue::parameter_list(
3556                        parameter,
3557                        parts.try_map(
3558                            |value| {
3559                                let actual = value.shape();
3560                                match value.kind {
3561                                    ConstantValueKind::List(ConstantListValue::Generic(value))
3562                                        if actual.can_flow_to(&item_shape) =>
3563                                    {
3564                                        Ok(value)
3565                                    }
3566                                    _ => Err(constant_list_element_mismatch(&item_shape, actual)),
3567                                }
3568                            },
3569                            |tail| {
3570                                let actual = tail.shape();
3571                                match tail {
3572                                    ConstantListValue::ParameterList(value)
3573                                        if actual.can_flow_to(&ValueShape::List(Box::new(
3574                                            item_shape.clone(),
3575                                        ))) =>
3576                                    {
3577                                        Ok(value)
3578                                    }
3579                                    _ => Err(constant_list_tail_mismatch(&item_shape, actual)),
3580                                }
3581                            },
3582                        )?,
3583                    )
3584                }
3585                crate::plan::ValueRepresentation::Stored(shape) => ConstantListValue::list(
3586                    shape,
3587                    parts.try_map(
3588                        |value| {
3589                            let actual = value.shape();
3590                            let value = match value.kind {
3591                                ConstantValueKind::List(ConstantListValue::ParameterList(
3592                                    value,
3593                                )) => ConstantStoredListValue::ParameterList(value),
3594                                ConstantValueKind::List(ConstantListValue::Int(value)) => {
3595                                    ConstantStoredListValue::Int(value)
3596                                }
3597                                ConstantValueKind::List(ConstantListValue::String(value)) => {
3598                                    ConstantStoredListValue::String(value)
3599                                }
3600                                ConstantValueKind::List(ConstantListValue::BitArray(value)) => {
3601                                    ConstantStoredListValue::BitArray(value)
3602                                }
3603                                ConstantValueKind::List(ConstantListValue::UtfCodepoint(value)) => {
3604                                    ConstantStoredListValue::UtfCodepoint(value)
3605                                }
3606                                ConstantValueKind::List(ConstantListValue::Custom(value)) => {
3607                                    ConstantStoredListValue::Custom(value)
3608                                }
3609                                ConstantValueKind::List(ConstantListValue::External(value)) => {
3610                                    ConstantStoredListValue::External(value)
3611                                }
3612                                ConstantValueKind::List(ConstantListValue::Float(value)) => {
3613                                    ConstantStoredListValue::Float(value)
3614                                }
3615                                ConstantValueKind::List(ConstantListValue::Bool(value)) => {
3616                                    ConstantStoredListValue::Bool(value)
3617                                }
3618                                ConstantValueKind::List(ConstantListValue::Nil(value)) => {
3619                                    ConstantStoredListValue::Nil(value)
3620                                }
3621                                ConstantValueKind::List(ConstantListValue::Tuple(value)) => {
3622                                    ConstantStoredListValue::Tuple(value)
3623                                }
3624                                ConstantValueKind::List(ConstantListValue::List(value)) => {
3625                                    ConstantStoredListValue::List(value)
3626                                }
3627                                ConstantValueKind::List(ConstantListValue::Function(value)) => {
3628                                    ConstantStoredListValue::Function(value)
3629                                }
3630                                _ => {
3631                                    return Err(constant_list_element_mismatch(
3632                                        &item_shape,
3633                                        actual,
3634                                    ));
3635                                }
3636                            };
3637                            if actual.can_flow_to(&item_shape) {
3638                                Ok(value)
3639                            } else {
3640                                Err(constant_list_element_mismatch(&item_shape, actual))
3641                            }
3642                        },
3643                        |tail| {
3644                            let actual = tail.shape();
3645                            match tail {
3646                                ConstantListValue::List(value)
3647                                    if actual.can_flow_to(&ValueShape::List(Box::new(
3648                                        item_shape.clone(),
3649                                    ))) =>
3650                                {
3651                                    Ok(value)
3652                                }
3653                                _ => Err(constant_list_tail_mismatch(&item_shape, actual)),
3654                            }
3655                        },
3656                    )?,
3657                ),
3658            },
3659            ValueShape::Function(shape) => ConstantListValue::function(
3660                (**shape).clone(),
3661                parts.try_map(
3662                    |value| {
3663                        let actual = value.shape();
3664                        match value.kind {
3665                            ConstantValueKind::Function(value)
3666                                if actual.can_flow_to(&item_shape) =>
3667                            {
3668                                Ok(value)
3669                            }
3670                            _ => Err(constant_list_element_mismatch(&item_shape, actual)),
3671                        }
3672                    },
3673                    |tail| {
3674                        let actual = tail.shape();
3675                        match tail {
3676                            ConstantListValue::Function(value)
3677                                if actual.can_flow_to(&ValueShape::List(Box::new(
3678                                    item_shape.clone(),
3679                                ))) =>
3680                            {
3681                                Ok(value)
3682                            }
3683                            _ => Err(constant_list_tail_mismatch(&item_shape, actual)),
3684                        }
3685                    },
3686                )?,
3687            ),
3688        };
3689
3690        Ok(Self {
3691            kind: ConstantValueKind::List(value),
3692        })
3693    }
3694
3695    pub(crate) fn bit_array(segments: Box<[ConstantBitArraySegment]>) -> Self {
3696        Self {
3697            kind: ConstantValueKind::BitArray(ConstantBitArrayValue {
3698                kind: ConstantBitArrayValueKind::Value(segments),
3699            }),
3700        }
3701    }
3702
3703    pub(crate) fn custom(
3704        shape: CustomValueShape,
3705        constructor: CustomConstructor,
3706        fields: Box<[Self]>,
3707    ) -> Self {
3708        Self {
3709            kind: ConstantValueKind::Custom(ConstantCustomValue {
3710                shape,
3711                kind: ConstantCustomValueKind::Construction(ConstantCustomConstruction {
3712                    constructor,
3713                    fields,
3714                }),
3715            }),
3716        }
3717    }
3718
3719    pub(crate) fn function(shape: FunctionShape, reference: FunctionReference) -> Self {
3720        let value = ConstantFunctionValue::function_reference(shape, reference);
3721        Self {
3722            kind: ConstantValueKind::Function(value),
3723        }
3724    }
3725
3726    pub(crate) fn constructor_function(
3727        shape: FunctionShape,
3728        return_: CustomValueShape,
3729        constructor: CustomConstructor,
3730    ) -> Self {
3731        let value = ConstantFunctionValue::constructor(shape, return_, constructor);
3732        Self {
3733            kind: ConstantValueKind::Function(value),
3734        }
3735    }
3736
3737    pub(crate) fn reference(instantiation: ConstantInstantiation) -> Self {
3738        let kind = match instantiation.kind {
3739            ConstantInstantiationKind::Int(value) => {
3740                ConstantValueKind::Int(ConstantIntValue::Reference(value))
3741            }
3742            ConstantInstantiationKind::String(value) => {
3743                ConstantValueKind::String(ConstantStringValue::Reference(value))
3744            }
3745            ConstantInstantiationKind::BitArray(value) => {
3746                ConstantValueKind::BitArray(ConstantBitArrayValue {
3747                    kind: ConstantBitArrayValueKind::Reference(value),
3748                })
3749            }
3750            ConstantInstantiationKind::Custom(value) => {
3751                ConstantValueKind::Custom(ConstantCustomValue {
3752                    shape: value.shape().clone(),
3753                    kind: ConstantCustomValueKind::Reference(value),
3754                })
3755            }
3756            ConstantInstantiationKind::Float(value) => {
3757                ConstantValueKind::Float(ConstantFloatValue::Reference(value))
3758            }
3759            ConstantInstantiationKind::Bool(value) => {
3760                ConstantValueKind::Bool(ConstantBoolValue::Reference(value))
3761            }
3762            ConstantInstantiationKind::Nil(value) => {
3763                ConstantValueKind::Nil(ConstantNilValue::Reference(value))
3764            }
3765            ConstantInstantiationKind::Tuple(value) => {
3766                ConstantValueKind::Tuple(ConstantTupleValue {
3767                    shape: value.shape().clone(),
3768                    kind: ConstantTupleValueKind::Reference(value),
3769                })
3770            }
3771            ConstantInstantiationKind::List(value) => {
3772                ConstantValueKind::List(ConstantListValue::reference(value))
3773            }
3774            ConstantInstantiationKind::Function(value) => {
3775                ConstantValueKind::Function(ConstantFunctionValue::reference(value))
3776            }
3777        };
3778        Self { kind }
3779    }
3780
3781    pub(crate) fn shape(&self) -> ValueShape {
3782        match &self.kind {
3783            ConstantValueKind::Int(_) => ValueShape::Int,
3784            ConstantValueKind::Float(_) => ValueShape::Float,
3785            ConstantValueKind::String(_) => ValueShape::String,
3786            ConstantValueKind::Bool(_) => ValueShape::Bool,
3787            ConstantValueKind::Nil(_) => ValueShape::Nil,
3788            ConstantValueKind::Tuple(value) => ValueShape::Tuple(value.shape.clone()),
3789            ConstantValueKind::List(value) => value.shape(),
3790            ConstantValueKind::BitArray(_) => ValueShape::BitArray,
3791            ConstantValueKind::Custom(value) => ValueShape::Custom(value.shape.clone()),
3792            ConstantValueKind::Function(value) => {
3793                ValueShape::Function(Box::new(value.shape().clone()))
3794            }
3795        }
3796    }
3797
3798    pub(crate) fn into_int(self) -> Option<ConstantIntValue> {
3799        match self.kind {
3800            ConstantValueKind::Int(value) => Some(value),
3801            _ => None,
3802        }
3803    }
3804
3805    pub(crate) fn into_float(self) -> Option<ConstantFloatValue> {
3806        match self.kind {
3807            ConstantValueKind::Float(value) => Some(value),
3808            _ => None,
3809        }
3810    }
3811
3812    pub(crate) fn into_string(self) -> Option<ConstantStringValue> {
3813        match self.kind {
3814            ConstantValueKind::String(value) => Some(value),
3815            _ => None,
3816        }
3817    }
3818
3819    pub(crate) fn into_bit_array(self) -> Option<ConstantBitArrayValue> {
3820        match self.kind {
3821            ConstantValueKind::BitArray(value) => Some(value),
3822            _ => None,
3823        }
3824    }
3825
3826    pub(crate) fn into_bool(self) -> Option<ConstantBoolValue> {
3827        match self.kind {
3828            ConstantValueKind::Bool(value) => Some(value),
3829            _ => None,
3830        }
3831    }
3832
3833    pub(crate) fn into_nil(self) -> Option<ConstantNilValue> {
3834        match self.kind {
3835            ConstantValueKind::Nil(value) => Some(value),
3836            _ => None,
3837        }
3838    }
3839
3840    fn into_list(self) -> Option<ConstantListValue> {
3841        match self.kind {
3842            ConstantValueKind::List(value) => Some(value),
3843            _ => None,
3844        }
3845    }
3846}
3847
3848impl ConstantTupleValue {
3849    pub(crate) fn shape(&self) -> &[ValueShape] {
3850        &self.shape
3851    }
3852
3853    pub(crate) fn kind(&self) -> &ConstantTupleValueKind {
3854        &self.kind
3855    }
3856}
3857
3858impl ConstantBitArrayValue {
3859    pub(crate) fn kind(&self) -> &ConstantBitArrayValueKind {
3860        &self.kind
3861    }
3862}
3863
3864impl ConstantCustomValue {
3865    pub(crate) fn shape(&self) -> &CustomValueShape {
3866        &self.shape
3867    }
3868
3869    pub(crate) fn kind(&self) -> &ConstantCustomValueKind {
3870        &self.kind
3871    }
3872}
3873
3874impl ConstantCustomConstruction {
3875    pub(crate) fn constructor(&self) -> &CustomConstructor {
3876        &self.constructor
3877    }
3878
3879    pub(crate) fn fields(&self) -> &[ConstantValue] {
3880        &self.fields
3881    }
3882}
3883
3884impl MaterializedConstantCustomConstruction {
3885    pub(crate) fn new(constructor: CustomConstructor, fields: Vec<super::Expr>) -> Self {
3886        Self {
3887            constructor,
3888            fields: fields.into_boxed_slice(),
3889        }
3890    }
3891
3892    pub(crate) fn into_parts(self) -> (CustomConstructor, Box<[super::Expr]>) {
3893        (self.constructor, self.fields)
3894    }
3895}
3896
3897fn constant_list_element_mismatch(
3898    expected: &ValueShape,
3899    actual: ValueShape,
3900) -> ConstantListConstructionError {
3901    ConstantListConstructionError::TypeMismatch {
3902        expected: expected.value_type(),
3903        actual: actual.value_type(),
3904    }
3905}
3906
3907fn constant_list_tail_mismatch(
3908    expected: &ValueShape,
3909    actual: ValueShape,
3910) -> ConstantListConstructionError {
3911    ConstantListConstructionError::TypeMismatch {
3912        expected: ValueType::List(Box::new(expected.value_type())),
3913        actual: actual.value_type(),
3914    }
3915}
3916
3917#[cfg(test)]
3918mod tests {
3919    use super::function::ConstantFunctionTemplate;
3920    use super::list::{ConstantListTemplate, ConstantParameterListListTemplateId};
3921    use super::{
3922        ConstantBitArraySegment, ConstantBitArrayTemplateId, ConstantBoolTemplateId,
3923        ConstantCustomTemplateId, ConstantFloatTemplateId, ConstantInstantiation,
3924        ConstantInstantiationKind, ConstantIntTemplateId, ConstantListConstructionError,
3925        ConstantListInstantiation, ConstantListValue, ConstantNilTemplateId,
3926        ConstantStringTemplateId, ConstantTemplate, ConstantTemplateId, ConstantTemplateSignature,
3927        ConstantTemplates, ConstantTupleTemplateId, ConstantValue,
3928        MaterializedConstantCustomConstruction, TypedConstantInstantiation,
3929    };
3930    use crate::plan::module::{
3931        CustomListExpr, CustomListItem, ExternalListExpr, ExternalListItem, GenericListExpr,
3932        GenericListItem,
3933    };
3934    use crate::plan::{
3935        BitArrayExpr, BitArrayListExpr, BitArrayListItem, BitArraySegment, BoolExpr, BoolListExpr,
3936        BoolListItem, CustomConstruction, CustomConstructor, CustomConstructorField,
3937        CustomConstructorRefinement, CustomExpr, CustomTypeName, CustomValueShape, Endianness,
3938        Expr, ExternalTypeName, ExternalValueShape, FloatBitSize, FloatExpr, FloatListExpr,
3939        FloatListItem, FunctionExpr, FunctionListExpr, FunctionListItem, FunctionReference,
3940        FunctionShape, IntExpr, ListExpr, ListListExpr, ListListItem, ModuleId, NilExpr,
3941        NilListExpr, NilListItem, PanicSite, ParameterListListExpr, ParameterListListItem,
3942        StoredListExpr, StringEncoding, StringExpr, StringListExpr, StringListItem, TupleExpr,
3943        TupleListExpr, TupleListItem, TypeParameterId, TypeScheme, TypeSubstitution,
3944        UtfCodepointListExpr, UtfCodepointListItem, ValueShape, ValueStorageShape, ValueType,
3945        monomorphic_function_instantiation,
3946    };
3947
3948    #[test]
3949    fn local_constant_alias_materialization_preserves_foreign_owner() {
3950        let scheme = TypeScheme::new(0);
3951        let root_signature = ConstantTemplateSignature::int(
3952            ConstantTemplateId::in_module(ModuleId::root(), 0),
3953            0,
3954            scheme,
3955        );
3956        let foreign = TypedConstantInstantiation::in_module(
3957            ModuleId::new(1),
3958            ConstantIntTemplateId(0),
3959            TypeSubstitution::from_arguments(Vec::new()),
3960            (),
3961        );
3962        let local = TypedConstantInstantiation::in_module(
3963            ModuleId::root(),
3964            ConstantIntTemplateId(0),
3965            TypeSubstitution::from_arguments(Vec::new()),
3966            (),
3967        );
3968        let templates = ConstantTemplates::from_module_entries(
3969            ModuleId::root(),
3970            vec![(
3971                ConstantTemplate::new(root_signature, "alias".into()),
3972                ConstantValue::reference(ConstantInstantiation::from_int(foreign.clone())),
3973            )],
3974        );
3975
3976        assert_eq!(
3977            templates.materialize_int(&local),
3978            IntExpr::constant(super::ConstantIntReference(foreign)),
3979        );
3980    }
3981
3982    #[test]
3983    fn external_function_constants_materialize_targets_and_aliases() {
3984        let external = ExternalValueShape::new(
3985            ExternalTypeName::new("application".into(), "main".into(), "Resource".into()),
3986            Vec::new(),
3987        );
3988        let shape = FunctionShape::new(Vec::new(), ValueShape::External(external));
3989        let reference =
3990            FunctionReference::new(monomorphic_function_instantiation(0, shape.clone()));
3991        let scheme = TypeScheme::new(0);
3992        let base = ConstantTemplateSignature::function(
3993            ConstantTemplateId::new(0),
3994            0,
3995            scheme.clone(),
3996            shape.clone(),
3997        );
3998        let alias = ConstantTemplateSignature::function(
3999            ConstantTemplateId::new(1),
4000            1,
4001            scheme,
4002            shape.clone(),
4003        );
4004        let base_instantiation = base
4005            .try_instantiate(Vec::new())
4006            .expect("a monomorphic external function constant should instantiate");
4007        let alias_instantiation = alias
4008            .try_instantiate(Vec::new())
4009            .expect("a monomorphic external function alias should instantiate");
4010        let substitution = TypeSubstitution::from_arguments(Vec::new());
4011        let expected_alias = ConstantFunctionTemplate::from_shape(&shape, 1).instantiate(
4012            ModuleId::root(),
4013            substitution.clone(),
4014            shape.clone(),
4015        );
4016        let templates = ConstantTemplates::from_entries(vec![
4017            (
4018                ConstantTemplate::new(base, "resource".into()),
4019                ConstantValue::function(shape.clone(), reference.clone()),
4020            ),
4021            (
4022                ConstantTemplate::new(alias, "resource_alias".into()),
4023                ConstantValue::reference(base_instantiation),
4024            ),
4025        ]);
4026        let expected_target = Expr::function(FunctionExpr::reference(reference.clone()));
4027        let expected_alias = Expr::function(FunctionExpr::constant(expected_alias));
4028
4029        assert_eq!(
4030            templates.materialize_value(&ConstantValue::function(shape, reference), &substitution,),
4031            expected_target,
4032        );
4033        assert_eq!(
4034            templates.materialize_value(
4035                &ConstantValue::reference(alias_instantiation),
4036                &substitution,
4037            ),
4038            expected_alias,
4039        );
4040    }
4041
4042    #[test]
4043    fn constant_references_materialize_every_top_level_family() {
4044        let monomorphic = TypeScheme::new(0);
4045        let int_base =
4046            ConstantTemplateSignature::int(ConstantTemplateId::new(0), 0, monomorphic.clone());
4047        let int_alias =
4048            ConstantTemplateSignature::int(ConstantTemplateId::new(1), 1, monomorphic.clone());
4049        let int_reference = int_base
4050            .try_instantiate(Vec::new())
4051            .expect("a monomorphic Int constant should instantiate without arguments");
4052
4053        let string_base =
4054            ConstantTemplateSignature::string(ConstantTemplateId::new(2), 0, monomorphic.clone());
4055        let string_alias =
4056            ConstantTemplateSignature::string(ConstantTemplateId::new(3), 1, monomorphic.clone());
4057        let string_reference = string_base
4058            .try_instantiate(Vec::new())
4059            .expect("a monomorphic String constant should instantiate without arguments");
4060
4061        let float_base =
4062            ConstantTemplateSignature::float(ConstantTemplateId::new(4), 0, monomorphic.clone());
4063        let float_alias =
4064            ConstantTemplateSignature::float(ConstantTemplateId::new(5), 1, monomorphic.clone());
4065        let float_reference = float_base
4066            .try_instantiate(Vec::new())
4067            .expect("a monomorphic Float constant should instantiate without arguments");
4068
4069        let bool_base =
4070            ConstantTemplateSignature::bool(ConstantTemplateId::new(6), 0, monomorphic.clone());
4071        let bool_alias =
4072            ConstantTemplateSignature::bool(ConstantTemplateId::new(7), 1, monomorphic.clone());
4073        let bool_reference = bool_base
4074            .try_instantiate(Vec::new())
4075            .expect("a monomorphic Bool constant should instantiate without arguments");
4076
4077        let nil_base =
4078            ConstantTemplateSignature::nil(ConstantTemplateId::new(8), 0, monomorphic.clone());
4079        let nil_alias =
4080            ConstantTemplateSignature::nil(ConstantTemplateId::new(9), 1, monomorphic.clone());
4081        let nil_reference = nil_base
4082            .try_instantiate(Vec::new())
4083            .expect("a monomorphic Nil constant should instantiate without arguments");
4084
4085        let bit_array_base = ConstantTemplateSignature::bit_array(
4086            ConstantTemplateId::new(10),
4087            0,
4088            monomorphic.clone(),
4089        );
4090        let bit_array_alias = ConstantTemplateSignature::bit_array(
4091            ConstantTemplateId::new(11),
4092            1,
4093            monomorphic.clone(),
4094        );
4095        let bit_array_reference = bit_array_base
4096            .try_instantiate(Vec::new())
4097            .expect("a monomorphic BitArray constant should instantiate without arguments");
4098
4099        let custom_shape = CustomValueShape::new(
4100            CustomTypeName::new("geam".into(), "main".into(), "Token".into()),
4101            Vec::new(),
4102            CustomConstructorRefinement::Exact(0),
4103        );
4104        let constructor = CustomConstructor::new(
4105            custom_shape.type_().clone(),
4106            "Token".into(),
4107            0,
4108            vec![CustomConstructorField::new(None, ValueType::Int)],
4109        );
4110        let custom_base = ConstantTemplateSignature::custom(
4111            ConstantTemplateId::new(12),
4112            0,
4113            monomorphic.clone(),
4114            custom_shape.clone(),
4115        );
4116        let custom_alias = ConstantTemplateSignature::custom(
4117            ConstantTemplateId::new(13),
4118            1,
4119            monomorphic.clone(),
4120            custom_shape.clone(),
4121        );
4122        let custom_reference = custom_base
4123            .try_instantiate(Vec::new())
4124            .expect("a monomorphic custom constant should instantiate without arguments");
4125
4126        let tuple_shape = vec![ValueShape::Int, ValueShape::String].into_boxed_slice();
4127        let tuple_base = ConstantTemplateSignature::tuple(
4128            ConstantTemplateId::new(14),
4129            0,
4130            monomorphic.clone(),
4131            tuple_shape.clone(),
4132        );
4133        let tuple_alias = ConstantTemplateSignature::tuple(
4134            ConstantTemplateId::new(15),
4135            1,
4136            monomorphic.clone(),
4137            tuple_shape.clone(),
4138        );
4139        let tuple_reference = tuple_base
4140            .try_instantiate(Vec::new())
4141            .expect("a monomorphic tuple constant should instantiate without arguments");
4142
4143        let function_shape = FunctionShape::new(vec![ValueShape::Int], ValueShape::String);
4144        let function_reference = FunctionReference::new(monomorphic_function_instantiation(
4145            3,
4146            function_shape.clone(),
4147        ));
4148        let function_base = ConstantTemplateSignature::function(
4149            ConstantTemplateId::new(16),
4150            0,
4151            monomorphic.clone(),
4152            function_shape.clone(),
4153        );
4154        let function_alias = ConstantTemplateSignature::function(
4155            ConstantTemplateId::new(17),
4156            1,
4157            monomorphic.clone(),
4158            function_shape.clone(),
4159        );
4160        let function_reference_constant = function_base
4161            .try_instantiate(Vec::new())
4162            .expect("a monomorphic function constant should instantiate without arguments");
4163
4164        let constructor_function_shape = FunctionShape::new(
4165            vec![ValueShape::Int],
4166            ValueShape::Custom(custom_shape.clone()),
4167        );
4168        let constructor_function = ConstantTemplateSignature::function(
4169            ConstantTemplateId::new(18),
4170            0,
4171            monomorphic,
4172            constructor_function_shape.clone(),
4173        );
4174
4175        let empty_bits = ConstantValue::bit_array(Box::new([]));
4176        let empty_bits_value = empty_bits
4177            .clone()
4178            .into_bit_array()
4179            .expect("a BitArray constant should retain its family");
4180        let bit_array = ConstantValue::bit_array(
4181            vec![
4182                ConstantBitArraySegment::Int {
4183                    value: ConstantValue::reference(int_reference.clone())
4184                        .into_int()
4185                        .expect("an Int reference should retain its family"),
4186                    bit_size: 12,
4187                    endianness: Endianness::Little,
4188                },
4189                ConstantBitArraySegment::Float {
4190                    value: ConstantValue::reference(float_reference.clone())
4191                        .into_float()
4192                        .expect("a Float reference should retain its family"),
4193                    bit_size: FloatBitSize::Sixteen,
4194                    endianness: Endianness::Big,
4195                },
4196                ConstantBitArraySegment::String {
4197                    value: ConstantValue::reference(string_reference.clone())
4198                        .into_string()
4199                        .expect("a String reference should retain its family"),
4200                    encoding: StringEncoding::Utf16(Endianness::Little),
4201                },
4202                ConstantBitArraySegment::Bits(empty_bits_value.clone()),
4203                ConstantBitArraySegment::SizedBits {
4204                    value: empty_bits_value,
4205                    bit_size: 0,
4206                    site: PanicSite::unknown(),
4207                },
4208            ]
4209            .into_boxed_slice(),
4210        );
4211
4212        let entries = vec![
4213            (
4214                ConstantTemplate::new(int_base.clone(), "int".into()),
4215                ConstantValue::int(7.into()),
4216            ),
4217            (
4218                ConstantTemplate::new(int_alias.clone(), "int_alias".into()),
4219                ConstantValue::reference(int_reference.clone()),
4220            ),
4221            (
4222                ConstantTemplate::new(string_base.clone(), "string".into()),
4223                ConstantValue::string_concatenation(
4224                    ConstantValue::string("ge".into())
4225                        .into_string()
4226                        .expect("a String constant should retain its family"),
4227                    ConstantValue::string("am".into())
4228                        .into_string()
4229                        .expect("a String constant should retain its family"),
4230                ),
4231            ),
4232            (
4233                ConstantTemplate::new(string_alias.clone(), "string_alias".into()),
4234                ConstantValue::reference(string_reference.clone()),
4235            ),
4236            (
4237                ConstantTemplate::new(float_base.clone(), "float".into()),
4238                ConstantValue::float(1.5),
4239            ),
4240            (
4241                ConstantTemplate::new(float_alias.clone(), "float_alias".into()),
4242                ConstantValue::reference(float_reference.clone()),
4243            ),
4244            (
4245                ConstantTemplate::new(bool_base.clone(), "bool".into()),
4246                ConstantValue::bool(true),
4247            ),
4248            (
4249                ConstantTemplate::new(bool_alias.clone(), "bool_alias".into()),
4250                ConstantValue::reference(bool_reference),
4251            ),
4252            (
4253                ConstantTemplate::new(nil_base.clone(), "nil".into()),
4254                ConstantValue::nil(),
4255            ),
4256            (
4257                ConstantTemplate::new(nil_alias.clone(), "nil_alias".into()),
4258                ConstantValue::reference(nil_reference),
4259            ),
4260            (
4261                ConstantTemplate::new(bit_array_base.clone(), "bits".into()),
4262                bit_array,
4263            ),
4264            (
4265                ConstantTemplate::new(bit_array_alias.clone(), "bits_alias".into()),
4266                ConstantValue::reference(bit_array_reference),
4267            ),
4268            (
4269                ConstantTemplate::new(custom_base.clone(), "token".into()),
4270                ConstantValue::custom(
4271                    custom_shape.clone(),
4272                    constructor.clone(),
4273                    vec![ConstantValue::reference(int_reference.clone())].into_boxed_slice(),
4274                ),
4275            ),
4276            (
4277                ConstantTemplate::new(custom_alias.clone(), "token_alias".into()),
4278                ConstantValue::reference(custom_reference),
4279            ),
4280            (
4281                ConstantTemplate::new(tuple_base.clone(), "pair".into()),
4282                ConstantValue::tuple(
4283                    tuple_shape,
4284                    vec![
4285                        ConstantValue::reference(int_reference),
4286                        ConstantValue::reference(string_reference),
4287                    ]
4288                    .into_boxed_slice(),
4289                ),
4290            ),
4291            (
4292                ConstantTemplate::new(tuple_alias.clone(), "pair_alias".into()),
4293                ConstantValue::reference(tuple_reference),
4294            ),
4295            (
4296                ConstantTemplate::new(function_base.clone(), "function".into()),
4297                ConstantValue::function(function_shape.clone(), function_reference.clone()),
4298            ),
4299            (
4300                ConstantTemplate::new(function_alias.clone(), "function_alias".into()),
4301                ConstantValue::reference(function_reference_constant.clone()),
4302            ),
4303            (
4304                ConstantTemplate::new(constructor_function.clone(), "constructor".into()),
4305                ConstantValue::constructor_function(
4306                    constructor_function_shape,
4307                    custom_shape.clone(),
4308                    constructor.clone(),
4309                ),
4310            ),
4311        ];
4312        let templates = ConstantTemplates::from_entries(entries);
4313        let empty = TypeSubstitution::from_arguments(Vec::new());
4314
4315        assert_eq!(
4316            templates.materialize_value(&ConstantValue::float(2.5), &empty),
4317            Expr::float(FloatExpr::value(2.5)),
4318        );
4319        assert_eq!(
4320            templates.materialize_value(&ConstantValue::bool(false), &empty),
4321            Expr::bool(BoolExpr::value(false)),
4322        );
4323        assert_eq!(
4324            templates.materialize_value(&ConstantValue::nil(), &empty),
4325            Expr::nil(NilExpr::value()),
4326        );
4327        assert_eq!(
4328            templates.materialize_value(
4329                &ConstantValue::tuple(
4330                    vec![ValueShape::Int].into_boxed_slice(),
4331                    vec![ConstantValue::int(9.into())].into_boxed_slice(),
4332                ),
4333                &empty,
4334            ),
4335            Expr::tuple(TupleExpr::value(
4336                vec![Expr::int(IntExpr::value(9.into()))],
4337                vec![ValueType::Int],
4338            )),
4339        );
4340        assert_eq!(
4341            templates.materialize_value(
4342                &ConstantValue::custom(
4343                    custom_shape.clone(),
4344                    constructor.clone(),
4345                    vec![ConstantValue::int(9.into())].into_boxed_slice(),
4346                ),
4347                &empty,
4348            ),
4349            Expr::custom(CustomExpr::from_construction(
4350                custom_shape.clone(),
4351                CustomConstruction::from_constant(MaterializedConstantCustomConstruction::new(
4352                    constructor.clone(),
4353                    vec![Expr::int(IntExpr::value(9.into()))],
4354                )),
4355            )),
4356        );
4357        assert_eq!(
4358            templates.materialize_value(
4359                &ConstantValue::function(function_shape.clone(), function_reference.clone()),
4360                &empty,
4361            ),
4362            Expr::function(FunctionExpr::reference(function_reference.clone())),
4363        );
4364
4365        assert_eq!(templates.headers().len(), 19);
4366        assert_eq!(
4367            templates.header(ConstantTemplateId::new(18)).name(),
4368            "constructor"
4369        );
4370        let int_alias_instantiation =
4371            TypedConstantInstantiation::new(ConstantIntTemplateId(1), empty.clone(), ());
4372        assert_eq!(
4373            int_alias.try_instantiate(Vec::new()),
4374            Some(ConstantInstantiation {
4375                kind: ConstantInstantiationKind::Int(int_alias_instantiation.clone()),
4376            }),
4377        );
4378        assert_eq!(
4379            templates.materialize_int(&int_alias_instantiation),
4380            IntExpr::value(7.into()),
4381        );
4382        let string_alias_instantiation =
4383            TypedConstantInstantiation::new(ConstantStringTemplateId(1), empty.clone(), ());
4384        assert_eq!(
4385            string_alias.try_instantiate(Vec::new()),
4386            Some(ConstantInstantiation {
4387                kind: ConstantInstantiationKind::String(string_alias_instantiation.clone()),
4388            }),
4389        );
4390        assert_eq!(
4391            templates.materialize_string(&string_alias_instantiation),
4392            StringExpr::concatenate(
4393                StringExpr::value("ge".into()),
4394                StringExpr::value("am".into()),
4395            ),
4396        );
4397        let float_alias_instantiation =
4398            TypedConstantInstantiation::new(ConstantFloatTemplateId(1), empty.clone(), ());
4399        assert_eq!(
4400            float_alias.try_instantiate(Vec::new()),
4401            Some(ConstantInstantiation {
4402                kind: ConstantInstantiationKind::Float(float_alias_instantiation.clone()),
4403            }),
4404        );
4405        assert_eq!(
4406            templates.materialize_float(&float_alias_instantiation),
4407            FloatExpr::value(1.5),
4408        );
4409        let bool_alias_instantiation =
4410            TypedConstantInstantiation::new(ConstantBoolTemplateId(1), empty.clone(), ());
4411        assert_eq!(
4412            bool_alias.try_instantiate(Vec::new()),
4413            Some(ConstantInstantiation {
4414                kind: ConstantInstantiationKind::Bool(bool_alias_instantiation.clone()),
4415            }),
4416        );
4417        assert_eq!(
4418            templates.materialize_bool(&bool_alias_instantiation),
4419            BoolExpr::value(true),
4420        );
4421        let nil_alias_instantiation =
4422            TypedConstantInstantiation::new(ConstantNilTemplateId(1), empty.clone(), ());
4423        assert_eq!(
4424            nil_alias.try_instantiate(Vec::new()),
4425            Some(ConstantInstantiation {
4426                kind: ConstantInstantiationKind::Nil(nil_alias_instantiation.clone()),
4427            }),
4428        );
4429        assert_eq!(
4430            templates.materialize_nil(&nil_alias_instantiation),
4431            NilExpr::value(),
4432        );
4433        let bit_array_alias_instantiation =
4434            TypedConstantInstantiation::new(ConstantBitArrayTemplateId(1), empty.clone(), ());
4435        assert_eq!(
4436            bit_array_alias.try_instantiate(Vec::new()),
4437            Some(ConstantInstantiation {
4438                kind: ConstantInstantiationKind::BitArray(bit_array_alias_instantiation.clone()),
4439            }),
4440        );
4441        assert_eq!(
4442            templates.materialize_bit_array(&bit_array_alias_instantiation),
4443            BitArrayExpr::value(vec![
4444                BitArraySegment::Int {
4445                    value: IntExpr::value(7.into()),
4446                    bit_size: 12,
4447                    endianness: Endianness::Little,
4448                },
4449                BitArraySegment::Float {
4450                    value: FloatExpr::value(1.5),
4451                    bit_size: FloatBitSize::Sixteen,
4452                    endianness: Endianness::Big,
4453                },
4454                BitArraySegment::String {
4455                    value: StringExpr::concatenate(
4456                        StringExpr::value("ge".into()),
4457                        StringExpr::value("am".into()),
4458                    ),
4459                    encoding: StringEncoding::Utf16(Endianness::Little),
4460                },
4461                BitArraySegment::Bits(BitArrayExpr::value(Vec::new())),
4462                BitArraySegment::SizedBits {
4463                    value: BitArrayExpr::value(Vec::new()),
4464                    size: crate::plan::BitArrayBitsSize::Fixed(0),
4465                    site: PanicSite::unknown(),
4466                },
4467            ]),
4468        );
4469        let custom_alias_instantiation = TypedConstantInstantiation::new(
4470            ConstantCustomTemplateId(1),
4471            empty.clone(),
4472            custom_shape.clone(),
4473        );
4474        assert_eq!(
4475            custom_alias.try_instantiate(Vec::new()),
4476            Some(ConstantInstantiation {
4477                kind: ConstantInstantiationKind::Custom(custom_alias_instantiation.clone()),
4478            }),
4479        );
4480        assert_eq!(
4481            templates.materialize_custom(&custom_alias_instantiation),
4482            CustomExpr::from_construction(
4483                custom_shape.clone(),
4484                CustomConstruction::from_constant(MaterializedConstantCustomConstruction::new(
4485                    constructor.clone(),
4486                    vec![Expr::int(IntExpr::value(7.into()))],
4487                )),
4488            ),
4489        );
4490        let tuple_alias_instantiation = TypedConstantInstantiation::new(
4491            ConstantTupleTemplateId(1),
4492            empty.clone(),
4493            vec![ValueShape::Int, ValueShape::String].into_boxed_slice(),
4494        );
4495        assert_eq!(
4496            tuple_alias.try_instantiate(Vec::new()),
4497            Some(ConstantInstantiation {
4498                kind: ConstantInstantiationKind::Tuple(tuple_alias_instantiation.clone()),
4499            }),
4500        );
4501        assert_eq!(
4502            templates.materialize_tuple(&tuple_alias_instantiation),
4503            TupleExpr::value(
4504                vec![
4505                    Expr::int(IntExpr::value(7.into())),
4506                    Expr::string(StringExpr::concatenate(
4507                        StringExpr::value("ge".into()),
4508                        StringExpr::value("am".into()),
4509                    )),
4510                ],
4511                vec![ValueType::Int, ValueType::String],
4512            ),
4513        );
4514        let function_alias_instantiation = ConstantFunctionTemplate::from_shape(&function_shape, 1)
4515            .instantiate(
4516                crate::plan::ModuleId::root(),
4517                empty.clone(),
4518                function_shape.clone(),
4519            );
4520        assert_eq!(
4521            function_alias.try_instantiate(Vec::new()),
4522            Some(ConstantInstantiation {
4523                kind: ConstantInstantiationKind::Function(function_alias_instantiation),
4524            }),
4525        );
4526        let constructor_function_shape =
4527            FunctionShape::new(vec![ValueShape::Int], ValueShape::Custom(custom_shape));
4528        let constructor_function_instantiation =
4529            ConstantFunctionTemplate::from_shape(&constructor_function_shape, 0).instantiate(
4530                crate::plan::ModuleId::root(),
4531                empty,
4532                constructor_function_shape,
4533            );
4534        assert_eq!(
4535            constructor_function.try_instantiate(Vec::new()),
4536            Some(ConstantInstantiation {
4537                kind: ConstantInstantiationKind::Function(constructor_function_instantiation),
4538            }),
4539        );
4540    }
4541
4542    #[test]
4543    fn function_constant_targets_and_references_materialize_every_return_family() {
4544        let source = r#"
4545pub type Token { Token(Int) }
4546
4547fn identity(value: value) { value }
4548fn int_value() { 1 }
4549fn float_value() { 1.5 }
4550fn string_value() { "one" }
4551fn bit_array_value() { <<1>> }
4552fn codepoint_value() {
4553  let assert <<value:utf8_codepoint>> = <<65>>
4554  value
4555}
4556fn custom_value() { Token(1) }
4557fn bool_value() { True }
4558fn nil_value() { Nil }
4559fn tuple_value() { #(1) }
4560fn list_value() { [1] }
4561fn function_value() { int_value }
4562
4563const generic_function = identity
4564const generic_alias = generic_function
4565const int_function = int_value
4566const int_alias = int_function
4567const float_function = float_value
4568const float_alias = float_function
4569const string_function = string_value
4570const string_alias = string_function
4571const bit_array_function = bit_array_value
4572const bit_array_alias = bit_array_function
4573const codepoint_function = codepoint_value
4574const codepoint_alias = codepoint_function
4575const custom_function = custom_value
4576const custom_alias = custom_function
4577const bool_function = bool_value
4578const bool_alias = bool_function
4579const nil_function = nil_value
4580const nil_alias = nil_function
4581const tuple_function = tuple_value
4582const tuple_alias = tuple_function
4583const list_function = list_value
4584const list_alias = list_function
4585const function_function = function_value
4586const function_alias = function_function
4587const constructor_function = Token
4588const constructor_alias = constructor_function
4589
4590pub fn main() {
4591  #(
4592    generic_alias == generic_alias,
4593    int_alias == int_alias,
4594    float_alias == float_alias,
4595    string_alias == string_alias,
4596    bit_array_alias == bit_array_alias,
4597    codepoint_alias == codepoint_alias,
4598    custom_alias == custom_alias,
4599    bool_alias == bool_alias,
4600    nil_alias == nil_alias,
4601    tuple_alias == tuple_alias,
4602    list_alias == list_alias,
4603    function_alias == function_alias,
4604    constructor_alias == constructor_alias,
4605  )
4606}
4607"#;
4608        let typed = crate::compile_typed_module("main", "main.gleam", source)
4609            .expect("function constant fixture should compile");
4610        let module = crate::plan_module(typed).expect("function constant fixture should plan");
4611        let plan = crate::ExecutionPlan::from_module_plan(module);
4612        let value = crate::run_main(&plan, &mut Vec::new())
4613            .expect("function constant fixture should execute");
4614
4615        assert_eq!(
4616            value,
4617            crate::Value::Tuple(vec![
4618                crate::Value::Bool(true),
4619                crate::Value::Bool(true),
4620                crate::Value::Bool(true),
4621                crate::Value::Bool(true),
4622                crate::Value::Bool(true),
4623                crate::Value::Bool(true),
4624                crate::Value::Bool(true),
4625                crate::Value::Bool(true),
4626                crate::Value::Bool(true),
4627                crate::Value::Bool(true),
4628                crate::Value::Bool(true),
4629                crate::Value::Bool(true),
4630                crate::Value::Bool(false),
4631            ]),
4632        );
4633    }
4634
4635    #[test]
4636    fn generic_empty_list_references_materialize_every_item_shape() {
4637        let parameter = TypeParameterId(0);
4638        let base_signature = ConstantTemplateSignature::list(
4639            ConstantTemplateId::new(0),
4640            0,
4641            TypeScheme::new(1),
4642            ValueShape::Parameter(parameter),
4643        );
4644        let alias_signature = ConstantTemplateSignature::list(
4645            ConstantTemplateId::new(1),
4646            1,
4647            TypeScheme::new(1),
4648            ValueShape::Parameter(parameter),
4649        );
4650        let identity = base_signature
4651            .try_instantiate(vec![ValueShape::Parameter(parameter)])
4652            .expect("one parameter should match the generic constant scheme");
4653        let templates = ConstantTemplates::from_entries(vec![
4654            (
4655                ConstantTemplate::new(base_signature, "empty".into()),
4656                ConstantValue::try_list(ValueShape::Parameter(parameter), Vec::new(), None)
4657                    .expect("an uninhabited list constant may be empty"),
4658            ),
4659            (
4660                ConstantTemplate::new(alias_signature.clone(), "alias".into()),
4661                ConstantValue::reference(identity),
4662            ),
4663        ]);
4664
4665        let custom_shape = CustomValueShape::new(
4666            CustomTypeName::new("geam".into(), "main".into(), "Token".into()),
4667            Vec::new(),
4668            CustomConstructorRefinement::Exact(0),
4669        );
4670        let function_shape = FunctionShape::new(vec![ValueShape::Int], ValueShape::String);
4671        let external_shape = ExternalValueShape::new(
4672            ExternalTypeName::new("geam".into(), "main".into(), "Resource".into()),
4673            Vec::new(),
4674        );
4675        let item_shapes = vec![
4676            ValueShape::Parameter(parameter),
4677            ValueShape::Int,
4678            ValueShape::String,
4679            ValueShape::BitArray,
4680            ValueShape::UtfCodepoint,
4681            ValueShape::Custom(custom_shape),
4682            ValueShape::External(external_shape),
4683            ValueShape::Float,
4684            ValueShape::Bool,
4685            ValueShape::Nil,
4686            ValueShape::Tuple(vec![ValueShape::Int, ValueShape::String].into_boxed_slice()),
4687            ValueShape::List(Box::new(ValueShape::Parameter(TypeParameterId(1)))),
4688            ValueShape::List(Box::new(ValueShape::Bool)),
4689            ValueShape::Function(Box::new(function_shape)),
4690        ];
4691
4692        for item_shape in item_shapes {
4693            let arguments = vec![item_shape.clone()];
4694            let substitution = TypeSubstitution::from_arguments(arguments.clone());
4695            let instantiation =
4696                ConstantListTemplate::from_item_shape(ValueShape::Parameter(parameter), 1)
4697                    .instantiate(crate::plan::ModuleId::root(), substitution.clone());
4698            assert_eq!(
4699                alias_signature.try_instantiate(arguments),
4700                Some(ConstantInstantiation {
4701                    kind: ConstantInstantiationKind::List(instantiation.clone()),
4702                }),
4703            );
4704            let actual = match instantiation {
4705                ConstantListInstantiation::Generic(value) => {
4706                    ListExpr::Generic(templates.materialize_generic_list(&value))
4707                }
4708                ConstantListInstantiation::ParameterList(value) => {
4709                    ListExpr::ParameterList(templates.materialize_parameter_list_list(&value))
4710                }
4711                ConstantListInstantiation::Int(value) => {
4712                    ListExpr::Int(templates.materialize_int_list(&value))
4713                }
4714                ConstantListInstantiation::String(value) => {
4715                    ListExpr::String(templates.materialize_string_list(&value))
4716                }
4717                ConstantListInstantiation::BitArray(value) => {
4718                    ListExpr::BitArray(templates.materialize_bit_array_list(&value))
4719                }
4720                ConstantListInstantiation::UtfCodepoint(value) => {
4721                    ListExpr::UtfCodepoint(templates.materialize_utf_codepoint_list(&value))
4722                }
4723                ConstantListInstantiation::Custom(value) => {
4724                    ListExpr::Custom(templates.materialize_custom_list(&value))
4725                }
4726                ConstantListInstantiation::External(value) => {
4727                    ListExpr::External(templates.materialize_external_list(&value))
4728                }
4729                ConstantListInstantiation::Float(value) => {
4730                    ListExpr::Float(templates.materialize_float_list(&value))
4731                }
4732                ConstantListInstantiation::Bool(value) => {
4733                    ListExpr::Bool(templates.materialize_bool_list(&value))
4734                }
4735                ConstantListInstantiation::Nil(value) => {
4736                    ListExpr::Nil(templates.materialize_nil_list(&value))
4737                }
4738                ConstantListInstantiation::Tuple(value) => {
4739                    ListExpr::Tuple(templates.materialize_tuple_list(&value))
4740                }
4741                ConstantListInstantiation::List(value) => {
4742                    ListExpr::List(templates.materialize_list_list(&value))
4743                }
4744                ConstantListInstantiation::Function(value) => {
4745                    ListExpr::Function(templates.materialize_function_list(&value))
4746                }
4747            };
4748            assert_eq!(
4749                templates.materialize_list_value(
4750                    &ConstantListValue::Generic(
4751                        templates
4752                            .generic_list(super::ConstantGenericListTemplateId(0))
4753                            .clone(),
4754                    ),
4755                    &substitution,
4756                ),
4757                actual.clone(),
4758            );
4759            assert_eq!(
4760                actual,
4761                ListExpr::value(Vec::new(), item_shape.value_type()).with_item_shape(item_shape),
4762            );
4763        }
4764    }
4765
4766    #[test]
4767    fn nested_generic_list_values_materialize_parameter_and_stored_items() {
4768        let parameter = TypeParameterId(0);
4769        let nested_parameter = TypeParameterId(1);
4770        let templates = ConstantTemplates::from_entries(Vec::new());
4771        let generic = ConstantValue::try_list(ValueShape::Parameter(parameter), Vec::new(), None)
4772            .expect("a bare-parameter list constant may be empty")
4773            .into_list()
4774            .and_then(ConstantListValue::into_generic)
4775            .expect("the empty bare-parameter list should retain its generic storage");
4776
4777        let unresolved_nested_shape =
4778            ValueShape::List(Box::new(ValueShape::Parameter(nested_parameter)));
4779        assert_eq!(
4780            templates.materialize_list_value(
4781                &ConstantListValue::Generic(generic.clone()),
4782                &TypeSubstitution::from_arguments(vec![unresolved_nested_shape.clone()]),
4783            ),
4784            ListExpr::value(Vec::new(), unresolved_nested_shape.value_type())
4785                .with_item_shape(unresolved_nested_shape),
4786        );
4787        assert_eq!(
4788            templates.materialize_generic_stored_list_value(
4789                &generic,
4790                &TypeSubstitution::from_arguments(Vec::new()),
4791                &ValueStorageShape::List(Box::new(ValueShape::Parameter(nested_parameter))),
4792            ),
4793            StoredListExpr::ParameterList(ParameterListListExpr::value(
4794                ParameterListListItem::new(nested_parameter),
4795                Vec::new(),
4796            )),
4797        );
4798
4799        let nested = ConstantValue::try_list(
4800            ValueShape::List(Box::new(ValueShape::Parameter(parameter))),
4801            vec![
4802                ConstantValue::try_list(ValueShape::Parameter(parameter), Vec::new(), None)
4803                    .expect("a nested bare-parameter list element may be empty"),
4804            ],
4805            None,
4806        )
4807        .expect("a list may contain an empty bare-parameter list")
4808        .into_list()
4809        .expect("the nested constant should retain its list family");
4810        let nested_stored = nested
4811            .clone()
4812            .into_stored()
4813            .expect("the nested list should have stored outer-list representation");
4814
4815        assert_eq!(
4816            templates
4817                .materialize_list_value(&nested, &TypeSubstitution::from_arguments(Vec::new()),),
4818            ListExpr::ParameterList(ParameterListListExpr::value(
4819                ParameterListListItem::new(parameter),
4820                vec![GenericListExpr::value(
4821                    GenericListItem::new(parameter),
4822                    Vec::new(),
4823                )],
4824            )),
4825        );
4826        assert_eq!(
4827            templates.materialize_stored_list_value(
4828                &nested_stored,
4829                &TypeSubstitution::from_arguments(Vec::new()),
4830            ),
4831            StoredListExpr::ParameterList(ParameterListListExpr::value(
4832                ParameterListListItem::new(parameter),
4833                vec![GenericListExpr::value(
4834                    GenericListItem::new(parameter),
4835                    Vec::new(),
4836                )],
4837            )),
4838        );
4839        assert_eq!(
4840            templates.materialize_list_value(
4841                &nested,
4842                &TypeSubstitution::from_arguments(vec![ValueShape::Int]),
4843            ),
4844            ListExpr::List(ListListExpr::value(
4845                ListListItem::new(ValueStorageShape::Int),
4846                vec![StoredListExpr::Int(crate::plan::IntListExpr::value(
4847                    crate::plan::IntListItem,
4848                    Vec::new(),
4849                ))],
4850            )),
4851        );
4852        assert_eq!(
4853            templates.materialize_stored_list_value(
4854                &nested_stored,
4855                &TypeSubstitution::from_arguments(vec![ValueShape::Int]),
4856            ),
4857            StoredListExpr::List(ListListExpr::value(
4858                ListListItem::new(ValueStorageShape::Int),
4859                vec![StoredListExpr::Int(crate::plan::IntListExpr::value(
4860                    crate::plan::IntListItem,
4861                    Vec::new(),
4862                ))],
4863            )),
4864        );
4865
4866        let custom_shape = CustomValueShape::new(
4867            CustomTypeName::new("geam".into(), "main".into(), "Token".into()),
4868            Vec::new(),
4869            CustomConstructorRefinement::Exact(0),
4870        );
4871        let tuple_shape = vec![ValueShape::Int, ValueShape::String].into_boxed_slice();
4872        let function_shape = FunctionShape::new(vec![ValueShape::Int], ValueShape::String);
4873        let external_shape = ExternalValueShape::new(
4874            ExternalTypeName::new("geam".into(), "main".into(), "Resource".into()),
4875            Vec::new(),
4876        );
4877        let stored = vec![
4878            (
4879                ValueStorageShape::Int,
4880                StoredListExpr::Int(crate::plan::IntListExpr::value(
4881                    crate::plan::IntListItem,
4882                    Vec::new(),
4883                )),
4884            ),
4885            (
4886                ValueStorageShape::Float,
4887                StoredListExpr::Float(FloatListExpr::value(FloatListItem, Vec::new())),
4888            ),
4889            (
4890                ValueStorageShape::String,
4891                StoredListExpr::String(StringListExpr::value(StringListItem, Vec::new())),
4892            ),
4893            (
4894                ValueStorageShape::BitArray,
4895                StoredListExpr::BitArray(BitArrayListExpr::value(BitArrayListItem, Vec::new())),
4896            ),
4897            (
4898                ValueStorageShape::UtfCodepoint,
4899                StoredListExpr::UtfCodepoint(UtfCodepointListExpr::value(
4900                    UtfCodepointListItem,
4901                    Vec::new(),
4902                )),
4903            ),
4904            (
4905                ValueStorageShape::Custom(custom_shape.clone()),
4906                StoredListExpr::Custom(
4907                    CustomListExpr::value(
4908                        CustomListItem::new(custom_shape.type_().clone()),
4909                        Vec::new(),
4910                    )
4911                    .with_item_shape(ValueShape::Custom(custom_shape.clone())),
4912                ),
4913            ),
4914            (
4915                ValueStorageShape::External(external_shape.clone()),
4916                StoredListExpr::External(
4917                    ExternalListExpr::value(
4918                        ExternalListItem::new(external_shape.type_().clone()),
4919                        Vec::new(),
4920                    )
4921                    .with_item_shape(ValueShape::External(external_shape.clone())),
4922                ),
4923            ),
4924            (
4925                ValueStorageShape::Bool,
4926                StoredListExpr::Bool(BoolListExpr::value(BoolListItem, Vec::new())),
4927            ),
4928            (
4929                ValueStorageShape::Nil,
4930                StoredListExpr::Nil(NilListExpr::value(NilListItem, Vec::new())),
4931            ),
4932            (
4933                ValueStorageShape::Tuple(tuple_shape.clone()),
4934                StoredListExpr::Tuple(TupleListExpr::value(
4935                    TupleListItem::new(tuple_shape.iter().map(ValueShape::value_type).collect()),
4936                    Vec::new(),
4937                )),
4938            ),
4939            (
4940                ValueStorageShape::List(Box::new(ValueShape::Bool)),
4941                StoredListExpr::List(ListListExpr::value(
4942                    ListListItem::new(ValueStorageShape::Bool),
4943                    Vec::new(),
4944                )),
4945            ),
4946            (
4947                ValueStorageShape::Function(Box::new(function_shape.clone())),
4948                StoredListExpr::Function(FunctionListExpr::value(
4949                    FunctionListItem::new(function_shape.type_()),
4950                    Vec::new(),
4951                )),
4952            ),
4953        ];
4954        for (shape, expected) in stored {
4955            let stored_value = ConstantValue::try_list(shape.to_value_shape(), Vec::new(), None)
4956                .expect("an empty list should accept every stored item family")
4957                .into_list()
4958                .expect("the empty constant should retain its list family")
4959                .into_stored()
4960                .expect("a stored item family should use stored list representation");
4961            assert_eq!(
4962                templates.materialize_generic_stored_list_value(
4963                    &generic,
4964                    &TypeSubstitution::from_arguments(Vec::new()),
4965                    &shape,
4966                ),
4967                expected.clone(),
4968            );
4969            assert_eq!(
4970                templates.materialize_stored_list_value(
4971                    &stored_value,
4972                    &TypeSubstitution::from_arguments(Vec::new()),
4973                ),
4974                expected,
4975            );
4976        }
4977
4978        let external_list = ConstantValue::try_list(
4979            ValueShape::External(external_shape.clone()),
4980            Vec::new(),
4981            None,
4982        )
4983        .expect("an external constant list may be empty");
4984        let nested_external_list = ConstantValue::try_list(
4985            ValueShape::List(Box::new(ValueShape::External(external_shape.clone()))),
4986            vec![external_list],
4987            None,
4988        )
4989        .expect("a constant list may contain an external list")
4990        .into_list()
4991        .expect("the nested external constant should retain its list family");
4992        assert_eq!(
4993            templates.materialize_list_value(
4994                &nested_external_list,
4995                &TypeSubstitution::from_arguments(Vec::new()),
4996            ),
4997            ListExpr::List(ListListExpr::value(
4998                ListListItem::new(ValueStorageShape::External(external_shape.clone())),
4999                vec![StoredListExpr::External(
5000                    ExternalListExpr::value(
5001                        ExternalListItem::new(external_shape.type_().clone()),
5002                        Vec::new(),
5003                    )
5004                    .with_item_shape(ValueShape::External(external_shape)),
5005                )],
5006            )),
5007        );
5008
5009        let deeply_nested = ConstantValue::try_list(
5010            ValueShape::List(Box::new(ValueShape::List(Box::new(ValueShape::Parameter(
5011                parameter,
5012            ))))),
5013            vec![
5014                ConstantValue::try_list(
5015                    ValueShape::List(Box::new(ValueShape::Parameter(parameter))),
5016                    vec![
5017                        ConstantValue::try_list(ValueShape::Parameter(parameter), Vec::new(), None)
5018                            .expect("a nested bare-parameter list element may be empty"),
5019                    ],
5020                    None,
5021                )
5022                .expect("an outer list may store a parameter-list payload"),
5023            ],
5024            None,
5025        )
5026        .expect("a deeply nested list may store an empty bare-parameter leaf");
5027        assert_eq!(
5028            deeply_nested.shape(),
5029            ValueShape::List(Box::new(ValueShape::List(Box::new(ValueShape::List(
5030                Box::new(ValueShape::Parameter(parameter)),
5031            ))))),
5032        );
5033        let deeply_nested = deeply_nested
5034            .into_list()
5035            .expect("the deeply nested constant should retain its list family");
5036        assert_eq!(
5037            templates.materialize_list_value(
5038                &deeply_nested,
5039                &TypeSubstitution::from_arguments(Vec::new()),
5040            ),
5041            ListExpr::List(ListListExpr::value(
5042                ListListItem::new(ValueStorageShape::List(Box::new(ValueShape::Parameter(
5043                    parameter,
5044                )))),
5045                vec![StoredListExpr::ParameterList(ParameterListListExpr::value(
5046                    ParameterListListItem::new(parameter),
5047                    vec![GenericListExpr::value(
5048                        GenericListItem::new(parameter),
5049                        Vec::new(),
5050                    )],
5051                ))],
5052            )),
5053        );
5054        assert_eq!(
5055            templates.materialize_list_value(
5056                &deeply_nested,
5057                &TypeSubstitution::from_arguments(vec![ValueShape::Int]),
5058            ),
5059            ListExpr::List(ListListExpr::value(
5060                ListListItem::new(ValueStorageShape::List(Box::new(ValueShape::Int))),
5061                vec![StoredListExpr::List(ListListExpr::value(
5062                    ListListItem::new(ValueStorageShape::Int),
5063                    vec![StoredListExpr::Int(crate::plan::IntListExpr::value(
5064                        crate::plan::IntListItem,
5065                        Vec::new(),
5066                    ))],
5067                ))],
5068            )),
5069        );
5070    }
5071
5072    #[test]
5073    fn parameter_list_list_spread_reference_materializes_uninhabited_and_stored_items() {
5074        let parameter = TypeParameterId(0);
5075        let item_shape = ValueShape::List(Box::new(ValueShape::Parameter(parameter)));
5076        let generic_element = || {
5077            ConstantValue::try_list(ValueShape::Parameter(parameter), Vec::new(), None)
5078                .expect("a bare-parameter list element may be empty")
5079        };
5080        let tail = ConstantValue::try_list(item_shape.clone(), vec![generic_element()], None)
5081            .expect("a parameter-list tail should accept an empty generic list");
5082        let base = ConstantValue::try_list(item_shape.clone(), vec![generic_element()], Some(tail))
5083            .expect("a parameter-list spread should accept a matching tail");
5084        let base_signature = ConstantTemplateSignature::list(
5085            ConstantTemplateId::new(0),
5086            0,
5087            TypeScheme::new(1),
5088            item_shape.clone(),
5089        );
5090        let alias_signature = ConstantTemplateSignature::list(
5091            ConstantTemplateId::new(1),
5092            1,
5093            TypeScheme::new(1),
5094            item_shape,
5095        );
5096        let reference = base_signature
5097            .try_instantiate(vec![ValueShape::Parameter(parameter)])
5098            .expect("the parameter-list constant should accept its identity substitution");
5099        let templates = ConstantTemplates::from_entries(vec![
5100            (ConstantTemplate::new(base_signature, "base".into()), base),
5101            (
5102                ConstantTemplate::new(alias_signature, "alias".into()),
5103                ConstantValue::reference(reference),
5104            ),
5105        ]);
5106        let alias = ConstantListValue::ParameterList(
5107            templates
5108                .parameter_list_list(ConstantParameterListListTemplateId(1))
5109                .clone(),
5110        );
5111        let generic = GenericListExpr::value(GenericListItem::new(parameter), Vec::new());
5112
5113        assert_eq!(
5114            templates
5115                .materialize_list_value(&alias, &TypeSubstitution::from_arguments(Vec::new()),),
5116            ListExpr::ParameterList(ParameterListListExpr::spread(
5117                vec1::vec1![generic.clone()],
5118                ParameterListListExpr::value(ParameterListListItem::new(parameter), vec![generic],),
5119            )),
5120        );
5121
5122        let int_list = StoredListExpr::Int(crate::plan::IntListExpr::value(
5123            crate::plan::IntListItem,
5124            Vec::new(),
5125        ));
5126        assert_eq!(
5127            templates.materialize_list_value(
5128                &alias,
5129                &TypeSubstitution::from_arguments(vec![ValueShape::Int]),
5130            ),
5131            ListExpr::List(ListListExpr::spread(
5132                vec1::vec1![int_list.clone()],
5133                ListListExpr::value(ListListItem::new(ValueStorageShape::Int), vec![int_list],),
5134            )),
5135        );
5136    }
5137
5138    #[test]
5139    fn exact_list_references_materialize_every_item_family() {
5140        let monomorphic = TypeScheme::new(0);
5141        let custom_shape = CustomValueShape::new(
5142            CustomTypeName::new("geam".into(), "main".into(), "Token".into()),
5143            Vec::new(),
5144            CustomConstructorRefinement::Exact(0),
5145        );
5146        let constructor = CustomConstructor::new(
5147            custom_shape.type_().clone(),
5148            "Token".into(),
5149            0,
5150            vec![CustomConstructorField::new(None, ValueType::Int)],
5151        );
5152        let tuple_shape = vec![ValueShape::Int, ValueShape::String].into_boxed_slice();
5153        let function_shape = FunctionShape::new(vec![ValueShape::Int], ValueShape::String);
5154        let function_reference = FunctionReference::new(monomorphic_function_instantiation(
5155            5,
5156            function_shape.clone(),
5157        ));
5158
5159        let item_shapes = vec![
5160            ValueShape::Int,
5161            ValueShape::String,
5162            ValueShape::BitArray,
5163            ValueShape::UtfCodepoint,
5164            ValueShape::Custom(custom_shape.clone()),
5165            ValueShape::Float,
5166            ValueShape::Bool,
5167            ValueShape::Nil,
5168            ValueShape::Tuple(tuple_shape.clone()),
5169            ValueShape::List(Box::new(ValueShape::Int)),
5170            ValueShape::Function(Box::new(function_shape.clone())),
5171        ];
5172        let signatures = item_shapes
5173            .iter()
5174            .enumerate()
5175            .flat_map(|(index, shape)| {
5176                [
5177                    ConstantTemplateSignature::list(
5178                        ConstantTemplateId::new(index * 2),
5179                        0,
5180                        monomorphic.clone(),
5181                        shape.clone(),
5182                    ),
5183                    ConstantTemplateSignature::list(
5184                        ConstantTemplateId::new(index * 2 + 1),
5185                        1,
5186                        monomorphic.clone(),
5187                        shape.clone(),
5188                    ),
5189                ]
5190            })
5191            .collect::<Vec<_>>();
5192
5193        let int_tail =
5194            ConstantValue::try_list(ValueShape::Int, vec![ConstantValue::int(2.into())], None)
5195                .expect("an Int list tail should accept Int elements");
5196        let int_list = ConstantValue::try_list(
5197            ValueShape::Int,
5198            vec![ConstantValue::int(1.into())],
5199            Some(int_tail),
5200        )
5201        .expect("an Int list spread should accept an Int list tail");
5202
5203        let string_tail = ConstantValue::try_list(
5204            ValueShape::String,
5205            vec![ConstantValue::string("two".into())],
5206            None,
5207        )
5208        .expect("a String list tail should accept String elements");
5209        let string_list = ConstantValue::try_list(
5210            ValueShape::String,
5211            vec![ConstantValue::string("one".into())],
5212            Some(string_tail),
5213        )
5214        .expect("a String list spread should accept a String list tail");
5215
5216        let bit_array_tail = ConstantValue::try_list(
5217            ValueShape::BitArray,
5218            vec![ConstantValue::bit_array(Box::new([]))],
5219            None,
5220        )
5221        .expect("a BitArray list tail should accept BitArray elements");
5222        let bit_array_list = ConstantValue::try_list(
5223            ValueShape::BitArray,
5224            vec![ConstantValue::bit_array(Box::new([]))],
5225            Some(bit_array_tail),
5226        )
5227        .expect("a BitArray list spread should accept a BitArray list tail");
5228
5229        let utf_codepoint_list =
5230            ConstantValue::try_list(ValueShape::UtfCodepoint, Vec::new(), None)
5231                .expect("a UtfCodepoint constant list may be empty");
5232
5233        let token = |value: i64| {
5234            ConstantValue::custom(
5235                custom_shape.clone(),
5236                constructor.clone(),
5237                vec![ConstantValue::int(value.into())].into_boxed_slice(),
5238            )
5239        };
5240        let custom_tail = ConstantValue::try_list(
5241            ValueShape::Custom(custom_shape.clone()),
5242            vec![token(4)],
5243            None,
5244        )
5245        .expect("a custom list tail should accept matching custom elements");
5246        let custom_list = ConstantValue::try_list(
5247            ValueShape::Custom(custom_shape.clone()),
5248            vec![token(3)],
5249            Some(custom_tail),
5250        )
5251        .expect("a custom list spread should accept a matching custom list tail");
5252
5253        let float_tail =
5254            ConstantValue::try_list(ValueShape::Float, vec![ConstantValue::float(2.5)], None)
5255                .expect("a Float list tail should accept Float elements");
5256        let float_list = ConstantValue::try_list(
5257            ValueShape::Float,
5258            vec![ConstantValue::float(1.5)],
5259            Some(float_tail),
5260        )
5261        .expect("a Float list spread should accept a Float list tail");
5262
5263        let bool_tail =
5264            ConstantValue::try_list(ValueShape::Bool, vec![ConstantValue::bool(false)], None)
5265                .expect("a Bool list tail should accept Bool elements");
5266        let bool_list = ConstantValue::try_list(
5267            ValueShape::Bool,
5268            vec![ConstantValue::bool(true)],
5269            Some(bool_tail),
5270        )
5271        .expect("a Bool list spread should accept a Bool list tail");
5272
5273        let nil_tail = ConstantValue::try_list(ValueShape::Nil, vec![ConstantValue::nil()], None)
5274            .expect("a Nil list tail should accept Nil elements");
5275        let nil_list =
5276            ConstantValue::try_list(ValueShape::Nil, vec![ConstantValue::nil()], Some(nil_tail))
5277                .expect("a Nil list spread should accept a Nil list tail");
5278
5279        let pair = |number: i64, string: &str| {
5280            ConstantValue::tuple(
5281                tuple_shape.clone(),
5282                vec![
5283                    ConstantValue::int(number.into()),
5284                    ConstantValue::string(string.into()),
5285                ]
5286                .into_boxed_slice(),
5287            )
5288        };
5289        let tuple_tail = ConstantValue::try_list(
5290            ValueShape::Tuple(tuple_shape.clone()),
5291            vec![pair(2, "two")],
5292            None,
5293        )
5294        .expect("a tuple list tail should accept matching tuple elements");
5295        let tuple_list = ConstantValue::try_list(
5296            ValueShape::Tuple(tuple_shape.clone()),
5297            vec![pair(1, "one")],
5298            Some(tuple_tail),
5299        )
5300        .expect("a tuple list spread should accept a matching tuple list tail");
5301
5302        let int_element = |value: i64| {
5303            ConstantValue::try_list(
5304                ValueShape::Int,
5305                vec![ConstantValue::int(value.into())],
5306                None,
5307            )
5308            .expect("a nested Int list should accept Int elements")
5309        };
5310        let list_tail = ConstantValue::try_list(
5311            ValueShape::List(Box::new(ValueShape::Int)),
5312            vec![int_element(2)],
5313            None,
5314        )
5315        .expect("a nested list tail should accept matching lists");
5316        let list_list = ConstantValue::try_list(
5317            ValueShape::List(Box::new(ValueShape::Int)),
5318            vec![int_element(1)],
5319            Some(list_tail),
5320        )
5321        .expect("a nested list spread should accept a matching nested list tail");
5322
5323        let function_value =
5324            || ConstantValue::function(function_shape.clone(), function_reference.clone());
5325        let function_tail = ConstantValue::try_list(
5326            ValueShape::Function(Box::new(function_shape.clone())),
5327            vec![function_value()],
5328            None,
5329        )
5330        .expect("a function list tail should accept matching functions");
5331        let function_list = ConstantValue::try_list(
5332            ValueShape::Function(Box::new(function_shape.clone())),
5333            vec![function_value()],
5334            Some(function_tail),
5335        )
5336        .expect("a function list spread should accept a matching function list tail");
5337
5338        let base_values = vec![
5339            int_list,
5340            string_list,
5341            bit_array_list,
5342            utf_codepoint_list,
5343            custom_list,
5344            float_list,
5345            bool_list,
5346            nil_list,
5347            tuple_list,
5348            list_list,
5349            function_list,
5350        ];
5351        let mut entries = Vec::with_capacity(base_values.len() * 2);
5352        let mut aliases = Vec::with_capacity(base_values.len());
5353        for (index, value) in base_values.into_iter().enumerate() {
5354            let base_signature = signatures[index * 2].clone();
5355            let alias_signature = signatures[index * 2 + 1].clone();
5356            let reference = base_signature
5357                .try_instantiate(Vec::new())
5358                .expect("a monomorphic list constant should instantiate without arguments");
5359            let alias = ConstantValue::reference(reference);
5360            entries.push((
5361                ConstantTemplate::new(base_signature, format!("base_{index}").into()),
5362                value,
5363            ));
5364            entries.push((
5365                ConstantTemplate::new(alias_signature, format!("alias_{index}").into()),
5366                alias.clone(),
5367            ));
5368            aliases.push(alias);
5369        }
5370        let templates = ConstantTemplates::from_entries(entries);
5371
5372        let expected = vec![
5373            ListExpr::spread(
5374                vec![Expr::int(IntExpr::value(1.into()))],
5375                ListExpr::value(vec![Expr::int(IntExpr::value(2.into()))], ValueType::Int),
5376                ValueType::Int,
5377            ),
5378            ListExpr::spread(
5379                vec![Expr::string(StringExpr::value("one".into()))],
5380                ListExpr::value(
5381                    vec![Expr::string(StringExpr::value("two".into()))],
5382                    ValueType::String,
5383                ),
5384                ValueType::String,
5385            ),
5386            ListExpr::spread(
5387                vec![Expr::bit_array(BitArrayExpr::value(Vec::new()))],
5388                ListExpr::value(
5389                    vec![Expr::bit_array(BitArrayExpr::value(Vec::new()))],
5390                    ValueType::BitArray,
5391                ),
5392                ValueType::BitArray,
5393            ),
5394            ListExpr::value(Vec::new(), ValueType::UtfCodepoint),
5395            ListExpr::spread(
5396                vec![Expr::custom(
5397                    CustomExpr::try_constructor(
5398                        constructor.clone(),
5399                        vec![Expr::int(IntExpr::value(3.into()))],
5400                    )
5401                    .expect("the custom element should match its constructor"),
5402                )],
5403                ListExpr::value(
5404                    vec![Expr::custom(
5405                        CustomExpr::try_constructor(
5406                            constructor.clone(),
5407                            vec![Expr::int(IntExpr::value(4.into()))],
5408                        )
5409                        .expect("the custom tail element should match its constructor"),
5410                    )],
5411                    ValueType::Custom(custom_shape.type_().clone()),
5412                )
5413                .with_item_shape(ValueShape::Custom(custom_shape.clone())),
5414                ValueType::Custom(custom_shape.type_().clone()),
5415            )
5416            .with_item_shape(ValueShape::Custom(custom_shape)),
5417            ListExpr::spread(
5418                vec![Expr::float(FloatExpr::value(1.5))],
5419                ListExpr::value(vec![Expr::float(FloatExpr::value(2.5))], ValueType::Float),
5420                ValueType::Float,
5421            ),
5422            ListExpr::spread(
5423                vec![Expr::bool(BoolExpr::value(true))],
5424                ListExpr::value(vec![Expr::bool(BoolExpr::value(false))], ValueType::Bool),
5425                ValueType::Bool,
5426            ),
5427            ListExpr::spread(
5428                vec![Expr::nil(NilExpr::value())],
5429                ListExpr::value(vec![Expr::nil(NilExpr::value())], ValueType::Nil),
5430                ValueType::Nil,
5431            ),
5432            ListExpr::spread(
5433                vec![Expr::tuple(TupleExpr::value(
5434                    vec![
5435                        Expr::int(IntExpr::value(1.into())),
5436                        Expr::string(StringExpr::value("one".into())),
5437                    ],
5438                    vec![ValueType::Int, ValueType::String],
5439                ))],
5440                ListExpr::value(
5441                    vec![Expr::tuple(TupleExpr::value(
5442                        vec![
5443                            Expr::int(IntExpr::value(2.into())),
5444                            Expr::string(StringExpr::value("two".into())),
5445                        ],
5446                        vec![ValueType::Int, ValueType::String],
5447                    ))],
5448                    ValueType::Tuple(vec![ValueType::Int, ValueType::String]),
5449                ),
5450                ValueType::Tuple(vec![ValueType::Int, ValueType::String]),
5451            ),
5452            ListExpr::spread(
5453                vec![Expr::list(ListExpr::value(
5454                    vec![Expr::int(IntExpr::value(1.into()))],
5455                    ValueType::Int,
5456                ))],
5457                ListExpr::value(
5458                    vec![Expr::list(ListExpr::value(
5459                        vec![Expr::int(IntExpr::value(2.into()))],
5460                        ValueType::Int,
5461                    ))],
5462                    ValueType::List(Box::new(ValueType::Int)),
5463                ),
5464                ValueType::List(Box::new(ValueType::Int)),
5465            ),
5466            ListExpr::spread(
5467                vec![Expr::function(FunctionExpr::reference(
5468                    function_reference.clone(),
5469                ))],
5470                ListExpr::value(
5471                    vec![Expr::function(FunctionExpr::reference(
5472                        function_reference.clone(),
5473                    ))],
5474                    ValueType::Function(Box::new(function_shape.type_())),
5475                ),
5476                ValueType::Function(Box::new(function_shape.type_())),
5477            ),
5478        ];
5479
5480        for (index, expected) in expected.into_iter().enumerate() {
5481            let instantiation =
5482                ConstantListTemplate::from_item_shape(item_shapes[index].clone(), 1).instantiate(
5483                    crate::plan::ModuleId::root(),
5484                    TypeSubstitution::from_arguments(Vec::new()),
5485                );
5486            assert_eq!(
5487                signatures[index * 2 + 1].try_instantiate(Vec::new()),
5488                Some(ConstantInstantiation {
5489                    kind: ConstantInstantiationKind::List(instantiation.clone()),
5490                }),
5491            );
5492            assert_eq!(
5493                templates.materialize_value(
5494                    &aliases[index],
5495                    &TypeSubstitution::from_arguments(Vec::new()),
5496                ),
5497                Expr::list(expected),
5498            );
5499        }
5500    }
5501
5502    #[test]
5503    fn constant_template_instantiation_rejects_wrong_argument_count() {
5504        let signature = ConstantTemplateSignature::list(
5505            ConstantTemplateId::new(3),
5506            0,
5507            TypeScheme::new(1),
5508            ValueShape::Parameter(TypeParameterId(0)),
5509        );
5510
5511        assert_eq!(signature.try_instantiate(Vec::new()), None);
5512        let instantiation = signature
5513            .try_instantiate(vec![ValueShape::String])
5514            .expect("one argument should match the constant scheme");
5515        assert_eq!(
5516            ConstantValue::reference(instantiation).shape(),
5517            ValueShape::List(Box::new(ValueShape::String)),
5518        );
5519    }
5520
5521    #[test]
5522    fn constant_instantiations_preserve_every_family_through_substitution() {
5523        let parameter = TypeParameterId(0);
5524        let replacement = ValueShape::String;
5525        let substitution = TypeSubstitution::from_arguments(vec![replacement.clone()]);
5526        let custom_shape = CustomValueShape::new(
5527            CustomTypeName::new("geam".into(), "main".into(), "Boxed".into()),
5528            vec![ValueShape::Parameter(parameter)],
5529            CustomConstructorRefinement::Exact(0),
5530        );
5531        let tuple_shape = vec![ValueShape::Parameter(parameter)].into_boxed_slice();
5532
5533        let int = TypedConstantInstantiation::new(
5534            ConstantIntTemplateId(0),
5535            TypeSubstitution::from_arguments(vec![ValueShape::Parameter(parameter)]),
5536            (),
5537        );
5538        let string = TypedConstantInstantiation::new(
5539            ConstantStringTemplateId(0),
5540            TypeSubstitution::from_arguments(vec![ValueShape::Parameter(parameter)]),
5541            (),
5542        );
5543        let float = TypedConstantInstantiation::new(
5544            ConstantFloatTemplateId(0),
5545            TypeSubstitution::from_arguments(vec![ValueShape::Parameter(parameter)]),
5546            (),
5547        );
5548        let bool_ = TypedConstantInstantiation::new(
5549            super::ConstantBoolTemplateId(0),
5550            TypeSubstitution::from_arguments(vec![ValueShape::Parameter(parameter)]),
5551            (),
5552        );
5553        let nil = TypedConstantInstantiation::new(
5554            ConstantNilTemplateId(0),
5555            TypeSubstitution::from_arguments(vec![ValueShape::Parameter(parameter)]),
5556            (),
5557        );
5558        let custom = TypedConstantInstantiation::new(
5559            ConstantCustomTemplateId(0),
5560            TypeSubstitution::from_arguments(vec![ValueShape::Parameter(parameter)]),
5561            custom_shape.clone(),
5562        );
5563        let tuple = TypedConstantInstantiation::new(
5564            ConstantTupleTemplateId(0),
5565            TypeSubstitution::from_arguments(vec![ValueShape::Parameter(parameter)]),
5566            tuple_shape,
5567        );
5568
5569        let cases = [
5570            ConstantInstantiation::from_int(int.clone()),
5571            ConstantInstantiation::from_string(string.clone()),
5572            ConstantInstantiation::from_custom(custom.clone()),
5573            ConstantInstantiation::from_float(float.clone()),
5574            ConstantInstantiation::from_bool(bool_.clone()),
5575            ConstantInstantiation::from_nil(nil.clone()),
5576        ];
5577        let expected = [
5578            ConstantInstantiation::from_int(int.substitute_leaf(&substitution)),
5579            ConstantInstantiation::from_string(string.substitute_leaf(&substitution)),
5580            ConstantInstantiation::from_custom(custom.substitute_custom(&substitution)),
5581            ConstantInstantiation::from_float(float.substitute_leaf(&substitution)),
5582            ConstantInstantiation::from_bool(bool_.substitute_leaf(&substitution)),
5583            ConstantInstantiation::from_nil(nil.substitute_leaf(&substitution)),
5584        ];
5585
5586        for (value, expected) in cases.iter().zip(expected) {
5587            assert_eq!(value.substitute(&substitution), expected);
5588        }
5589        assert_eq!(
5590            ConstantInstantiation::from_tuple(tuple.clone()).substitute(&substitution),
5591            ConstantInstantiation::from_tuple(tuple.substitute_tuple(&substitution)),
5592        );
5593
5594        assert_eq!(
5595            super::ConstantIntReference(int.clone()).instantiation(),
5596            &int
5597        );
5598        assert_eq!(
5599            super::ConstantStringReference(string.clone()).instantiation(),
5600            &string,
5601        );
5602        assert_eq!(
5603            super::ConstantCustomReference(custom.clone()).instantiation(),
5604            &custom,
5605        );
5606        assert_eq!(
5607            super::ConstantFloatReference(float.clone()).instantiation(),
5608            &float,
5609        );
5610        assert_eq!(
5611            super::ConstantBoolReference(bool_.clone()).instantiation(),
5612            &bool_,
5613        );
5614        assert_eq!(
5615            super::ConstantNilReference(nil.clone()).instantiation(),
5616            &nil
5617        );
5618
5619        assert_eq!(ConstantValue::string("not int".into()).into_int(), None);
5620        assert_eq!(ConstantValue::int(1.into()).into_float(), None);
5621        assert_eq!(ConstantValue::int(1.into()).into_string(), None);
5622        assert_eq!(ConstantValue::int(1.into()).into_bit_array(), None);
5623        assert_eq!(ConstantValue::int(1.into()).into_bool(), None);
5624        assert_eq!(ConstantValue::int(1.into()).into_nil(), None);
5625        assert_eq!(ConstantValue::int(1.into()).into_list(), None);
5626    }
5627
5628    #[test]
5629    fn list_construction_rejects_uninhabited_and_mismatched_payloads() {
5630        let int_list =
5631            ConstantValue::try_list(ValueShape::Int, vec![ConstantValue::int(1.into())], None)
5632                .expect("an Int list should accept Int elements");
5633        let string_list = ConstantValue::try_list(
5634            ValueShape::String,
5635            vec![ConstantValue::string("one".into())],
5636            None,
5637        )
5638        .expect("a String list should accept String elements");
5639        let generic_list =
5640            ConstantValue::try_list(ValueShape::Parameter(TypeParameterId(0)), Vec::new(), None)
5641                .expect("a bare-parameter list may be empty");
5642        let utf_codepoint_list =
5643            ConstantValue::try_list(ValueShape::UtfCodepoint, Vec::new(), None)
5644                .expect("a UtfCodepoint list may be empty");
5645        let external_shape = ExternalValueShape::new(
5646            ExternalTypeName::new("geam".into(), "main".into(), "Resource".into()),
5647            Vec::new(),
5648        );
5649        let external_list = ConstantValue::try_list(
5650            ValueShape::External(external_shape.clone()),
5651            Vec::new(),
5652            None,
5653        )
5654        .expect("an external constant list may be empty");
5655
5656        assert_eq!(
5657            ConstantValue::try_list(ValueShape::Int, Vec::new(), Some(int_list.clone())),
5658            Err(ConstantListConstructionError::SpreadWithoutElements),
5659        );
5660        assert_eq!(
5661            ConstantValue::try_list(
5662                ValueShape::Parameter(TypeParameterId(0)),
5663                Vec::new(),
5664                Some(generic_list.clone()),
5665            ),
5666            Err(ConstantListConstructionError::SpreadWithoutElements),
5667        );
5668        assert_eq!(
5669            ConstantValue::try_list(
5670                ValueShape::UtfCodepoint,
5671                Vec::new(),
5672                Some(utf_codepoint_list.clone()),
5673            ),
5674            Err(ConstantListConstructionError::SpreadWithoutElements),
5675        );
5676        assert_eq!(
5677            ConstantValue::try_list(
5678                ValueShape::External(external_shape.clone()),
5679                Vec::new(),
5680                Some(external_list.clone()),
5681            ),
5682            Err(ConstantListConstructionError::SpreadWithoutElements),
5683        );
5684        assert_eq!(
5685            ConstantValue::try_list(
5686                ValueShape::Parameter(TypeParameterId(0)),
5687                vec![ConstantValue::int(1.into())],
5688                None,
5689            ),
5690            Err(ConstantListConstructionError::TypeMismatch {
5691                expected: ValueType::Parameter(TypeParameterId(0)),
5692                actual: ValueType::Int,
5693            }),
5694        );
5695        assert_eq!(
5696            ConstantValue::try_list(
5697                ValueShape::External(external_shape.clone()),
5698                vec![ConstantValue::int(1.into())],
5699                None,
5700            ),
5701            Err(ConstantListConstructionError::TypeMismatch {
5702                expected: ValueType::External(external_shape.type_().clone()),
5703                actual: ValueType::Int,
5704            }),
5705        );
5706        assert_eq!(
5707            ConstantValue::try_list(
5708                ValueShape::External(external_shape.clone()),
5709                vec![ConstantValue::int(1.into())],
5710                Some(external_list),
5711            ),
5712            Err(ConstantListConstructionError::TypeMismatch {
5713                expected: ValueType::External(external_shape.type_().clone()),
5714                actual: ValueType::Int,
5715            }),
5716        );
5717        assert_eq!(
5718            ConstantValue::try_list(
5719                ValueShape::UtfCodepoint,
5720                vec![ConstantValue::int(1.into())],
5721                None,
5722            ),
5723            Err(ConstantListConstructionError::TypeMismatch {
5724                expected: ValueType::UtfCodepoint,
5725                actual: ValueType::Int,
5726            }),
5727        );
5728        assert_eq!(
5729            ConstantValue::try_list(
5730                ValueShape::Parameter(TypeParameterId(0)),
5731                vec![ConstantValue::int(1.into())],
5732                Some(generic_list.clone()),
5733            ),
5734            Err(ConstantListConstructionError::TypeMismatch {
5735                expected: ValueType::Parameter(TypeParameterId(0)),
5736                actual: ValueType::Int,
5737            }),
5738        );
5739        assert_eq!(
5740            ConstantValue::try_list(
5741                ValueShape::UtfCodepoint,
5742                vec![ConstantValue::int(1.into())],
5743                Some(utf_codepoint_list),
5744            ),
5745            Err(ConstantListConstructionError::TypeMismatch {
5746                expected: ValueType::UtfCodepoint,
5747                actual: ValueType::Int,
5748            }),
5749        );
5750
5751        assert_eq!(
5752            ConstantValue::try_list(
5753                ValueShape::Int,
5754                vec![ConstantValue::string("one".into())],
5755                None,
5756            ),
5757            Err(ConstantListConstructionError::TypeMismatch {
5758                expected: ValueType::Int,
5759                actual: ValueType::String,
5760            }),
5761        );
5762        assert_eq!(
5763            ConstantValue::try_list(ValueShape::Float, vec![ConstantValue::int(1.into())], None,),
5764            Err(ConstantListConstructionError::TypeMismatch {
5765                expected: ValueType::Float,
5766                actual: ValueType::Int,
5767            }),
5768        );
5769        assert_eq!(
5770            ConstantValue::try_list(ValueShape::String, vec![ConstantValue::int(1.into())], None,),
5771            Err(ConstantListConstructionError::TypeMismatch {
5772                expected: ValueType::String,
5773                actual: ValueType::Int,
5774            }),
5775        );
5776        assert_eq!(
5777            ConstantValue::try_list(
5778                ValueShape::BitArray,
5779                vec![ConstantValue::int(1.into())],
5780                None,
5781            ),
5782            Err(ConstantListConstructionError::TypeMismatch {
5783                expected: ValueType::BitArray,
5784                actual: ValueType::Int,
5785            }),
5786        );
5787        assert_eq!(
5788            ConstantValue::try_list(ValueShape::Bool, vec![ConstantValue::int(1.into())], None,),
5789            Err(ConstantListConstructionError::TypeMismatch {
5790                expected: ValueType::Bool,
5791                actual: ValueType::Int,
5792            }),
5793        );
5794        assert_eq!(
5795            ConstantValue::try_list(ValueShape::Nil, vec![ConstantValue::int(1.into())], None,),
5796            Err(ConstantListConstructionError::TypeMismatch {
5797                expected: ValueType::Nil,
5798                actual: ValueType::Int,
5799            }),
5800        );
5801
5802        let custom_shape = CustomValueShape::new(
5803            CustomTypeName::new("geam".into(), "main".into(), "Token".into()),
5804            Vec::new(),
5805            CustomConstructorRefinement::Exact(0),
5806        );
5807        let constructor =
5808            CustomConstructor::new(custom_shape.type_().clone(), "Token".into(), 0, Vec::new());
5809        let custom = ConstantValue::custom(custom_shape.clone(), constructor.clone(), Box::new([]));
5810        let tuple = ConstantValue::tuple(
5811            vec![ValueShape::Int].into_boxed_slice(),
5812            vec![ConstantValue::int(1.into())].into_boxed_slice(),
5813        );
5814        let function_shape =
5815            FunctionShape::new(Vec::new(), ValueShape::Custom(custom_shape.clone()));
5816        let function = ConstantValue::constructor_function(
5817            function_shape.clone(),
5818            custom_shape.clone(),
5819            constructor,
5820        );
5821
5822        assert_eq!(
5823            ConstantValue::try_list(
5824                ValueShape::Custom(custom_shape.clone()),
5825                vec![ConstantValue::int(1.into())],
5826                None,
5827            ),
5828            Err(ConstantListConstructionError::TypeMismatch {
5829                expected: ValueType::Custom(custom_shape.type_().clone()),
5830                actual: ValueType::Int,
5831            }),
5832        );
5833        assert_eq!(
5834            ConstantValue::try_list(
5835                ValueShape::Tuple(vec![ValueShape::Int].into_boxed_slice()),
5836                vec![ConstantValue::int(1.into())],
5837                None,
5838            ),
5839            Err(ConstantListConstructionError::TypeMismatch {
5840                expected: ValueType::Tuple(vec![ValueType::Int]),
5841                actual: ValueType::Int,
5842            }),
5843        );
5844        assert_eq!(
5845            ConstantValue::try_list(
5846                ValueShape::List(Box::new(ValueShape::Int)),
5847                vec![ConstantValue::int(1.into())],
5848                None,
5849            ),
5850            Err(ConstantListConstructionError::TypeMismatch {
5851                expected: ValueType::List(Box::new(ValueType::Int)),
5852                actual: ValueType::Int,
5853            }),
5854        );
5855        assert_eq!(
5856            ConstantValue::try_list(
5857                ValueShape::List(Box::new(ValueShape::Parameter(TypeParameterId(0)))),
5858                vec![int_list.clone()],
5859                None,
5860            ),
5861            Err(ConstantListConstructionError::TypeMismatch {
5862                expected: ValueType::List(Box::new(ValueType::Parameter(TypeParameterId(0)))),
5863                actual: ValueType::List(Box::new(ValueType::Int)),
5864            }),
5865        );
5866        assert_eq!(
5867            ConstantValue::try_list(
5868                ValueShape::List(Box::new(ValueShape::Parameter(TypeParameterId(0)))),
5869                vec![ConstantValue::int(1.into())],
5870                None,
5871            ),
5872            Err(ConstantListConstructionError::TypeMismatch {
5873                expected: ValueType::List(Box::new(ValueType::Parameter(TypeParameterId(0)))),
5874                actual: ValueType::Int,
5875            }),
5876        );
5877        assert_eq!(
5878            ConstantValue::try_list(
5879                ValueShape::List(Box::new(ValueShape::List(Box::new(ValueShape::Parameter(
5880                    TypeParameterId(0)
5881                ),)))),
5882                vec![int_list.clone()],
5883                Some(int_list.clone()),
5884            ),
5885            Err(ConstantListConstructionError::TypeMismatch {
5886                expected: ValueType::List(Box::new(ValueType::List(Box::new(
5887                    ValueType::Parameter(TypeParameterId(0)),
5888                )))),
5889                actual: ValueType::List(Box::new(ValueType::Int)),
5890            }),
5891        );
5892        assert_eq!(
5893            ConstantValue::try_list(
5894                ValueShape::List(Box::new(ValueShape::Parameter(TypeParameterId(0)))),
5895                vec![
5896                    ConstantValue::try_list(
5897                        ValueShape::Parameter(TypeParameterId(0)),
5898                        Vec::new(),
5899                        None,
5900                    )
5901                    .expect("a bare-parameter list may be empty")
5902                ],
5903                Some(int_list.clone()),
5904            ),
5905            Err(ConstantListConstructionError::TypeMismatch {
5906                expected: ValueType::List(Box::new(ValueType::List(Box::new(
5907                    ValueType::Parameter(TypeParameterId(0)),
5908                )))),
5909                actual: ValueType::List(Box::new(ValueType::Int)),
5910            }),
5911        );
5912        assert_eq!(
5913            ConstantValue::try_list(
5914                ValueShape::List(Box::new(ValueShape::Int)),
5915                vec![generic_list],
5916                None,
5917            ),
5918            Err(ConstantListConstructionError::TypeMismatch {
5919                expected: ValueType::List(Box::new(ValueType::Int)),
5920                actual: ValueType::List(Box::new(ValueType::Parameter(TypeParameterId(0)))),
5921            }),
5922        );
5923        assert_eq!(
5924            ConstantValue::try_list(
5925                ValueShape::Function(Box::new(function_shape.clone())),
5926                vec![ConstantValue::int(1.into())],
5927                None,
5928            ),
5929            Err(ConstantListConstructionError::TypeMismatch {
5930                expected: ValueType::Function(Box::new(function_shape.type_())),
5931                actual: ValueType::Int,
5932            }),
5933        );
5934
5935        assert_eq!(
5936            ConstantValue::try_list(
5937                ValueShape::Int,
5938                vec![ConstantValue::int(1.into())],
5939                Some(ConstantValue::int(2.into())),
5940            ),
5941            Err(ConstantListConstructionError::TypeMismatch {
5942                expected: ValueType::List(Box::new(ValueType::Int)),
5943                actual: ValueType::Int,
5944            }),
5945        );
5946        assert_eq!(
5947            ConstantValue::try_list(
5948                ValueShape::Int,
5949                vec![ConstantValue::int(1.into())],
5950                Some(string_list.clone()),
5951            ),
5952            Err(ConstantListConstructionError::TypeMismatch {
5953                expected: ValueType::List(Box::new(ValueType::Int)),
5954                actual: ValueType::List(Box::new(ValueType::String)),
5955            }),
5956        );
5957        assert_eq!(
5958            ConstantValue::try_list(
5959                ValueShape::String,
5960                vec![ConstantValue::string("one".into())],
5961                Some(int_list.clone()),
5962            ),
5963            Err(ConstantListConstructionError::TypeMismatch {
5964                expected: ValueType::List(Box::new(ValueType::String)),
5965                actual: ValueType::List(Box::new(ValueType::Int)),
5966            }),
5967        );
5968        assert_eq!(
5969            ConstantValue::try_list(
5970                ValueShape::BitArray,
5971                vec![ConstantValue::bit_array(Box::new([]))],
5972                Some(int_list.clone()),
5973            ),
5974            Err(ConstantListConstructionError::TypeMismatch {
5975                expected: ValueType::List(Box::new(ValueType::BitArray)),
5976                actual: ValueType::List(Box::new(ValueType::Int)),
5977            }),
5978        );
5979        assert_eq!(
5980            ConstantValue::try_list(
5981                ValueShape::Float,
5982                vec![ConstantValue::float(1.5)],
5983                Some(int_list.clone()),
5984            ),
5985            Err(ConstantListConstructionError::TypeMismatch {
5986                expected: ValueType::List(Box::new(ValueType::Float)),
5987                actual: ValueType::List(Box::new(ValueType::Int)),
5988            }),
5989        );
5990        assert_eq!(
5991            ConstantValue::try_list(
5992                ValueShape::Bool,
5993                vec![ConstantValue::bool(true)],
5994                Some(int_list.clone()),
5995            ),
5996            Err(ConstantListConstructionError::TypeMismatch {
5997                expected: ValueType::List(Box::new(ValueType::Bool)),
5998                actual: ValueType::List(Box::new(ValueType::Int)),
5999            }),
6000        );
6001        assert_eq!(
6002            ConstantValue::try_list(
6003                ValueShape::Nil,
6004                vec![ConstantValue::nil()],
6005                Some(int_list.clone()),
6006            ),
6007            Err(ConstantListConstructionError::TypeMismatch {
6008                expected: ValueType::List(Box::new(ValueType::Nil)),
6009                actual: ValueType::List(Box::new(ValueType::Int)),
6010            }),
6011        );
6012        assert_eq!(
6013            ConstantValue::try_list(
6014                ValueShape::Custom(custom_shape.clone()),
6015                vec![custom],
6016                Some(int_list.clone()),
6017            ),
6018            Err(ConstantListConstructionError::TypeMismatch {
6019                expected: ValueType::List(Box::new(ValueType::Custom(
6020                    custom_shape.type_().clone(),
6021                ))),
6022                actual: ValueType::List(Box::new(ValueType::Int)),
6023            }),
6024        );
6025        assert_eq!(
6026            ConstantValue::try_list(
6027                ValueShape::Tuple(vec![ValueShape::Int].into_boxed_slice()),
6028                vec![tuple],
6029                Some(int_list.clone()),
6030            ),
6031            Err(ConstantListConstructionError::TypeMismatch {
6032                expected: ValueType::List(Box::new(ValueType::Tuple(vec![ValueType::Int]))),
6033                actual: ValueType::List(Box::new(ValueType::Int)),
6034            }),
6035        );
6036        assert_eq!(
6037            ConstantValue::try_list(
6038                ValueShape::List(Box::new(ValueShape::Int)),
6039                vec![int_list.clone()],
6040                Some(int_list.clone()),
6041            ),
6042            Err(ConstantListConstructionError::TypeMismatch {
6043                expected: ValueType::List(Box::new(ValueType::List(Box::new(ValueType::Int)))),
6044                actual: ValueType::List(Box::new(ValueType::Int)),
6045            }),
6046        );
6047        assert_eq!(
6048            ConstantValue::try_list(
6049                ValueShape::Function(Box::new(function_shape.clone())),
6050                vec![function],
6051                Some(int_list),
6052            ),
6053            Err(ConstantListConstructionError::TypeMismatch {
6054                expected: ValueType::List(Box::new(ValueType::Function(Box::new(
6055                    function_shape.type_(),
6056                )))),
6057                actual: ValueType::List(Box::new(ValueType::Int)),
6058            }),
6059        );
6060    }
6061}