rukalang/elab/
specialization.rs

1use super::helpers::{is_type_param, ty_to_type_expr};
2use super::prelude::*;
3
4impl Elaborator {
5    pub(super) fn elaborate_function_body(
6        &mut self,
7        function: &mut FunctionDecl,
8    ) -> Result<(), ElabError> {
9        let signature = self
10            .signatures
11            .get(&function.name)
12            .cloned()
13            .ok_or_else(|| ElabError::UnknownFunction {
14                name: function.name.clone(),
15            })?;
16        let mut locals = Vec::new();
17        for (param, (_, param_ty)) in function.params.iter().zip(signature.params.iter()) {
18            locals.push((param.name.clone(), param_ty.clone()));
19        }
20        let _ =
21            self.elaborate_block(&mut function.body, Some(&signature.return_ty), &mut locals)?;
22        Ok(())
23    }
24
25    pub(super) fn bind_meta_arg(
26        &self,
27        callee_name: &str,
28        param: &Param,
29        expr: &Expr,
30    ) -> Result<TemplateMetaBinding, ElabError> {
31        match (&param.ty.ty, expr) {
32            (TypeExpr::Named(name), Expr::String(value)) if name == "String" => {
33                Ok(TemplateMetaBinding::String(value.clone()))
34            }
35            (TypeExpr::Named(name), Expr::Int(value)) if name == "i64" => {
36                Ok(TemplateMetaBinding::Int(*value))
37            }
38            (TypeExpr::Named(name), Expr::Number(value)) if name == "i64" => {
39                let parsed = value
40                    .raw
41                    .parse::<i64>()
42                    .map_err(|_| ElabError::UnsupportedTypeExpr)?;
43                Ok(TemplateMetaBinding::Int(parsed))
44            }
45            (TypeExpr::Named(name), _) if name == "String" || name == "i64" => {
46                Err(ElabError::UnsupportedMetaArg {
47                    name: callee_name.to_owned(),
48                    param: param.name.clone(),
49                })
50            }
51            _ => Err(ElabError::UnsupportedMetaParamType {
52                name: callee_name.to_owned(),
53                param: param.name.clone(),
54            }),
55        }
56    }
57
58    pub(super) fn next_instance_name(&mut self, callee_name: &str) -> String {
59        let instance = self.next_function_instance_id;
60        self.next_function_instance_id += 1;
61        format!("{callee_name}[__inst_{instance}]")
62    }
63
64    pub(super) fn elaborate_call_runtime_args(
65        &mut self,
66        args: &mut Vec<CallArg>,
67        params: &[(OwnershipMode, Ty)],
68        locals: &mut Vec<(String, Ty)>,
69        callee_name: &str,
70    ) -> Result<(), ElabError> {
71        self.validate_runtime_call_args(args, params, locals, callee_name)
72    }
73
74    pub(super) fn resolve_function_signature(
75        &mut self,
76        function: &FunctionDecl,
77        type_params: &[String],
78        bindings: &BTreeMap<String, Ty>,
79    ) -> Result<FunctionSig, ElabError> {
80        let type_params = type_params.iter().cloned().collect::<BTreeSet<_>>();
81        let mut params = Vec::with_capacity(function.params.len());
82        for param in &function.params {
83            let ty = self.resolve_type_expr(&param.ty.ty, bindings, &type_params, None)?;
84            self.ensure_ty_instantiated(&ty)?;
85            params.push((param.ty.mode, ty));
86        }
87        let return_ty =
88            self.resolve_type_expr(&function.return_type.ty, bindings, &type_params, None)?;
89        self.ensure_ty_instantiated(&return_ty)?;
90        Ok(FunctionSig { params, return_ty })
91    }
92
93    pub(super) fn apply_type_bindings_to_function(
94        &mut self,
95        function: &mut FunctionDecl,
96        bindings: &BTreeMap<String, Ty>,
97        type_params: &[String],
98    ) -> Result<(), ElabError> {
99        let type_params = type_params.iter().cloned().collect::<BTreeSet<_>>();
100        for param in &mut function.params {
101            self.apply_type_bindings_to_type_ref(&mut param.ty, bindings, &type_params)?;
102        }
103        self.apply_type_bindings_to_type_ref(&mut function.return_type, bindings, &type_params)?;
104        self.apply_type_bindings_to_block(&mut function.body, bindings, &type_params)?;
105        Ok(())
106    }
107
108    pub(super) fn specialize_function_params(
109        &mut self,
110        function: &mut FunctionDecl,
111        variadic_pack_tys: &[Ty],
112    ) -> Result<(), ElabError> {
113        let original_params = function.params.clone();
114        let mut params = Vec::new();
115        for param in &original_params {
116            if is_type_param(param) || param.is_meta {
117                continue;
118            }
119            if param.is_variadic {
120                for (index, item_ty) in variadic_pack_tys.iter().enumerate() {
121                    let mut specialized = param.clone();
122                    specialized.name = format!("{}__{index}", param.name);
123                    specialized.is_meta = false;
124                    specialized.is_variadic = false;
125                    specialized.ty.ty = ty_to_type_expr(item_ty);
126                    params.push(specialized);
127                }
128            } else {
129                let mut specialized = param.clone();
130                specialized.is_meta = false;
131                specialized.is_variadic = false;
132                params.push(specialized);
133            }
134        }
135        function.params = params;
136        self.apply_variadic_param_substitutions(function, &original_params, variadic_pack_tys)?;
137        Ok(())
138    }
139
140    pub(super) fn apply_variadic_param_substitutions(
141        &mut self,
142        function: &mut FunctionDecl,
143        original_params: &[Param],
144        variadic_pack_tys: &[Ty],
145    ) -> Result<(), ElabError> {
146        let mut replacements = BTreeMap::new();
147        for original in original_params {
148            if !original.is_variadic {
149                continue;
150            }
151            let items = variadic_pack_tys
152                .iter()
153                .enumerate()
154                .map(|(index, _)| Expr::Ident {
155                    name: format!("{}__{index}", original.name),
156                    span: original.name_span,
157                })
158                .collect();
159            replacements.insert(
160                original.name.clone(),
161                Expr::Tuple {
162                    items,
163                    span: original.name_span,
164                },
165            );
166        }
167        self.apply_expr_replacements_to_block(&mut function.body, &replacements)
168    }
169
170    pub(super) fn apply_meta_bindings_to_function(
171        &mut self,
172        function: &mut FunctionDecl,
173        bindings: &BTreeMap<String, TemplateMetaBinding>,
174    ) -> Result<(), ElabError> {
175        self.apply_meta_bindings_to_block(&mut function.body, bindings)
176    }
177
178    pub(super) fn apply_expr_replacements_to_block(
179        &mut self,
180        block: &mut Block,
181        replacements: &BTreeMap<String, Expr>,
182    ) -> Result<(), ElabError> {
183        for stmt in &mut block.statements {
184            self.apply_expr_replacements_to_stmt(stmt, replacements)?;
185        }
186        Ok(())
187    }
188
189    pub(super) fn apply_expr_replacements_to_stmt(
190        &mut self,
191        stmt: &mut Stmt,
192        replacements: &BTreeMap<String, Expr>,
193    ) -> Result<(), ElabError> {
194        match stmt {
195            Stmt::Let { value, .. } | Stmt::Expr { expr: value, .. } => {
196                self.apply_expr_replacements_to_expr(value, replacements)
197            }
198            Stmt::Assign { value, .. } => self.apply_expr_replacements_to_expr(value, replacements),
199            Stmt::If {
200                condition,
201                then_block,
202                else_block,
203                ..
204            } => {
205                self.apply_expr_replacements_to_expr(condition, replacements)?;
206                self.apply_expr_replacements_to_block(then_block, replacements)?;
207                if let Some(else_block) = else_block {
208                    self.apply_expr_replacements_to_block(else_block, replacements)?;
209                }
210                Ok(())
211            }
212            Stmt::For { iterable, body, .. } => {
213                self.apply_expr_replacements_to_expr(iterable, replacements)?;
214                self.apply_expr_replacements_to_block(body, replacements)
215            }
216            Stmt::While { condition, body } => {
217                self.apply_expr_replacements_to_expr(condition, replacements)?;
218                self.apply_expr_replacements_to_block(body, replacements)
219            }
220            Stmt::Match { value, arms } => {
221                self.apply_expr_replacements_to_expr(value, replacements)?;
222                for arm in arms {
223                    self.apply_expr_replacements_to_block(&mut arm.body, replacements)?;
224                }
225                Ok(())
226            }
227            Stmt::Meta { body } => self.apply_expr_replacements_to_meta_block(body, replacements),
228        }
229    }
230
231    pub(super) fn apply_expr_replacements_to_meta_block(
232        &mut self,
233        block: &mut crate::syntax::ast::MetaBlock,
234        replacements: &BTreeMap<String, Expr>,
235    ) -> Result<(), ElabError> {
236        for stmt in &mut block.statements {
237            match stmt {
238                crate::syntax::ast::MetaStmt::Let { value, .. }
239                | crate::syntax::ast::MetaStmt::Expr { expr: value } => {
240                    self.apply_expr_replacements_to_meta_expr(value, replacements)?;
241                }
242                crate::syntax::ast::MetaStmt::Match { value, arms } => {
243                    self.apply_expr_replacements_to_meta_expr(value, replacements)?;
244                    for arm in arms {
245                        if let crate::syntax::ast::MetaMatchPattern::Quote(quoted) =
246                            &mut arm.pattern
247                        {
248                            self.apply_expr_replacements_to_quoted_code(quoted, replacements)?;
249                        }
250                        self.apply_expr_replacements_to_meta_expr(&mut arm.result, replacements)?;
251                    }
252                }
253                crate::syntax::ast::MetaStmt::Meta { body } => {
254                    self.apply_expr_replacements_to_meta_block(body, replacements)?;
255                }
256            }
257        }
258        Ok(())
259    }
260
261    pub(super) fn apply_expr_replacements_to_meta_expr(
262        &mut self,
263        expr: &mut crate::syntax::ast::MetaExpr,
264        replacements: &BTreeMap<String, Expr>,
265    ) -> Result<(), ElabError> {
266        match expr {
267            crate::syntax::ast::MetaExpr::Call { args, .. } => {
268                for arg in args {
269                    self.apply_expr_replacements_to_meta_expr(arg, replacements)?;
270                }
271                Ok(())
272            }
273            crate::syntax::ast::MetaExpr::BuildExpr(expr) => {
274                self.apply_expr_replacements_to_expr(expr, replacements)
275            }
276            crate::syntax::ast::MetaExpr::Quote(quoted) => {
277                self.apply_expr_replacements_to_quoted_code(quoted, replacements)
278            }
279            crate::syntax::ast::MetaExpr::Splice(value) => {
280                self.apply_expr_replacements_to_meta_expr(value, replacements)
281            }
282            crate::syntax::ast::MetaExpr::Ident(_)
283            | crate::syntax::ast::MetaExpr::Int(_)
284            | crate::syntax::ast::MetaExpr::Bool(_)
285            | crate::syntax::ast::MetaExpr::String(_)
286            | crate::syntax::ast::MetaExpr::Type(_) => Ok(()),
287        }
288    }
289
290    pub(super) fn apply_expr_replacements_to_quoted_code(
291        &mut self,
292        quoted: &mut crate::syntax::ast::QuotedCode,
293        replacements: &BTreeMap<String, Expr>,
294    ) -> Result<(), ElabError> {
295        match quoted {
296            crate::syntax::ast::QuotedCode::Expr(expr) => {
297                self.apply_expr_replacements_to_expr(expr, replacements)
298            }
299            crate::syntax::ast::QuotedCode::Type(_) => Ok(()),
300        }
301    }
302
303    pub(super) fn apply_expr_replacements_to_expr(
304        &mut self,
305        expr: &mut Expr,
306        replacements: &BTreeMap<String, Expr>,
307    ) -> Result<(), ElabError> {
308        match expr {
309            Expr::Ident { name, .. } => {
310                if let Some(replacement) = replacements.get(name) {
311                    *expr = replacement.clone();
312                }
313                Ok(())
314            }
315            Expr::Call { callee, args, .. } => {
316                self.apply_expr_replacements_to_expr(callee, replacements)?;
317                for arg in args {
318                    if let CallArg::Expr(expr) | CallArg::Spread(expr) = arg {
319                        self.apply_expr_replacements_to_expr(expr, replacements)?;
320                    }
321                }
322                Ok(())
323            }
324            Expr::IntrinsicCall { args, .. } => {
325                for arg in args {
326                    if let CallArg::Expr(expr) | CallArg::Spread(expr) = arg {
327                        self.apply_expr_replacements_to_expr(expr, replacements)?;
328                    }
329                }
330                Ok(())
331            }
332            Expr::Field { base, .. } | Expr::Prefix { value: base, .. } => {
333                self.apply_expr_replacements_to_expr(base, replacements)
334            }
335            Expr::Index { base, index } => {
336                self.apply_expr_replacements_to_expr(base, replacements)?;
337                self.apply_expr_replacements_to_expr(index, replacements)
338            }
339            Expr::SliceRange { base, start, end } => {
340                self.apply_expr_replacements_to_expr(base, replacements)?;
341                if let Some(start) = start {
342                    self.apply_expr_replacements_to_expr(start, replacements)?;
343                }
344                if let Some(end) = end {
345                    self.apply_expr_replacements_to_expr(end, replacements)?;
346                }
347                Ok(())
348            }
349            Expr::Binary { lhs, rhs, .. } => {
350                self.apply_expr_replacements_to_expr(lhs, replacements)?;
351                self.apply_expr_replacements_to_expr(rhs, replacements)
352            }
353            Expr::Relational { lhs, rhs, .. } => {
354                self.apply_expr_replacements_to_expr(lhs, replacements)?;
355                self.apply_expr_replacements_to_expr(rhs, replacements)
356            }
357            Expr::Array { items, .. } | Expr::Tuple { items, .. } => {
358                for item in items {
359                    self.apply_expr_replacements_to_expr(item, replacements)?;
360                }
361                Ok(())
362            }
363            Expr::StructLit { fields, .. } => {
364                for field in fields {
365                    self.apply_expr_replacements_to_expr(&mut field.value, replacements)?;
366                }
367                Ok(())
368            }
369            Expr::Block(block) => self.apply_expr_replacements_to_block(block, replacements),
370            Expr::Splice(meta) => self.apply_expr_replacements_to_meta_expr(meta, replacements),
371            Expr::Int(_) | Expr::Number(_) | Expr::String(_) | Expr::Bool(_) => Ok(()),
372        }
373    }
374
375    pub(super) fn apply_meta_bindings_to_block(
376        &mut self,
377        block: &mut Block,
378        bindings: &BTreeMap<String, TemplateMetaBinding>,
379    ) -> Result<(), ElabError> {
380        for stmt in &mut block.statements {
381            self.apply_meta_bindings_to_stmt(stmt, bindings)?;
382        }
383        Ok(())
384    }
385
386    pub(super) fn apply_meta_bindings_to_stmt(
387        &mut self,
388        stmt: &mut Stmt,
389        bindings: &BTreeMap<String, TemplateMetaBinding>,
390    ) -> Result<(), ElabError> {
391        match stmt {
392            Stmt::Let { value, .. } | Stmt::Expr { expr: value, .. } => {
393                self.apply_meta_bindings_to_expr(value, bindings)
394            }
395            Stmt::Assign { value, .. } => self.apply_meta_bindings_to_expr(value, bindings),
396            Stmt::If {
397                condition,
398                then_block,
399                else_block,
400                ..
401            } => {
402                self.apply_meta_bindings_to_expr(condition, bindings)?;
403                self.apply_meta_bindings_to_block(then_block, bindings)?;
404                if let Some(else_block) = else_block {
405                    self.apply_meta_bindings_to_block(else_block, bindings)?;
406                }
407                Ok(())
408            }
409            Stmt::For { iterable, body, .. } => {
410                self.apply_meta_bindings_to_expr(iterable, bindings)?;
411                self.apply_meta_bindings_to_block(body, bindings)
412            }
413            Stmt::While { condition, body } => {
414                self.apply_meta_bindings_to_expr(condition, bindings)?;
415                self.apply_meta_bindings_to_block(body, bindings)
416            }
417            Stmt::Match { value, arms } => {
418                self.apply_meta_bindings_to_expr(value, bindings)?;
419                for arm in arms {
420                    self.apply_meta_bindings_to_block(&mut arm.body, bindings)?;
421                }
422                Ok(())
423            }
424            Stmt::Meta { .. } => Ok(()),
425        }
426    }
427
428    pub(super) fn apply_meta_bindings_to_expr(
429        &mut self,
430        expr: &mut Expr,
431        bindings: &BTreeMap<String, TemplateMetaBinding>,
432    ) -> Result<(), ElabError> {
433        match expr {
434            Expr::Ident { name, .. } => {
435                if let Some(replacement) = bindings.get(name) {
436                    *expr = match replacement {
437                        TemplateMetaBinding::Int(value) => {
438                            Expr::Number(crate::syntax::ast::NumberLiteral {
439                                raw: value.to_string(),
440                            })
441                        }
442                        TemplateMetaBinding::String(value) => Expr::String(value.clone()),
443                        TemplateMetaBinding::Type(_) => return Ok(()),
444                    };
445                }
446                Ok(())
447            }
448            Expr::Call { callee, args, .. } => {
449                self.apply_meta_bindings_to_expr(callee, bindings)?;
450                for arg in args {
451                    if let CallArg::Expr(expr) | CallArg::Spread(expr) = arg {
452                        self.apply_meta_bindings_to_expr(expr, bindings)?;
453                    }
454                }
455                Ok(())
456            }
457            Expr::IntrinsicCall { args, .. } => {
458                for arg in args {
459                    if let CallArg::Expr(expr) | CallArg::Spread(expr) = arg {
460                        self.apply_meta_bindings_to_expr(expr, bindings)?;
461                    }
462                }
463                Ok(())
464            }
465            Expr::Field { base, .. } | Expr::Prefix { value: base, .. } => {
466                self.apply_meta_bindings_to_expr(base, bindings)
467            }
468            Expr::Index { base, index } => {
469                self.apply_meta_bindings_to_expr(base, bindings)?;
470                self.apply_meta_bindings_to_expr(index, bindings)
471            }
472            Expr::SliceRange { base, start, end } => {
473                self.apply_meta_bindings_to_expr(base, bindings)?;
474                if let Some(start) = start {
475                    self.apply_meta_bindings_to_expr(start, bindings)?;
476                }
477                if let Some(end) = end {
478                    self.apply_meta_bindings_to_expr(end, bindings)?;
479                }
480                Ok(())
481            }
482            Expr::Binary { lhs, rhs, .. } => {
483                self.apply_meta_bindings_to_expr(lhs, bindings)?;
484                self.apply_meta_bindings_to_expr(rhs, bindings)
485            }
486            Expr::Relational { lhs, rhs, .. } => {
487                self.apply_meta_bindings_to_expr(lhs, bindings)?;
488                self.apply_meta_bindings_to_expr(rhs, bindings)
489            }
490            Expr::Array { items, .. } | Expr::Tuple { items, .. } => {
491                for item in items {
492                    self.apply_meta_bindings_to_expr(item, bindings)?;
493                }
494                Ok(())
495            }
496            Expr::StructLit { fields, .. } => {
497                for field in fields {
498                    self.apply_meta_bindings_to_expr(&mut field.value, bindings)?;
499                }
500                Ok(())
501            }
502            Expr::Block(block) => self.apply_meta_bindings_to_block(block, bindings),
503            Expr::Int(_) | Expr::Number(_) | Expr::String(_) | Expr::Bool(_) | Expr::Splice(_) => {
504                Ok(())
505            }
506        }
507    }
508
509    pub(super) fn apply_type_bindings_to_block(
510        &mut self,
511        block: &mut Block,
512        bindings: &BTreeMap<String, Ty>,
513        type_params: &BTreeSet<String>,
514    ) -> Result<(), ElabError> {
515        for stmt in &mut block.statements {
516            self.apply_type_bindings_to_stmt(stmt, bindings, type_params)?;
517        }
518        Ok(())
519    }
520
521    pub(super) fn apply_type_bindings_to_stmt(
522        &mut self,
523        stmt: &mut Stmt,
524        bindings: &BTreeMap<String, Ty>,
525        type_params: &BTreeSet<String>,
526    ) -> Result<(), ElabError> {
527        match stmt {
528            Stmt::Let { value, .. } | Stmt::Expr { expr: value, .. } => {
529                self.apply_type_bindings_to_expr(value, bindings, type_params)
530            }
531            Stmt::Assign { value, .. } => {
532                self.apply_type_bindings_to_expr(value, bindings, type_params)
533            }
534            Stmt::If {
535                condition,
536                then_block,
537                else_block,
538                ..
539            } => {
540                self.apply_type_bindings_to_expr(condition, bindings, type_params)?;
541                self.apply_type_bindings_to_block(then_block, bindings, type_params)?;
542                if let Some(else_block) = else_block {
543                    self.apply_type_bindings_to_block(else_block, bindings, type_params)?;
544                }
545                Ok(())
546            }
547            Stmt::For { iterable, body, .. } => {
548                self.apply_type_bindings_to_expr(iterable, bindings, type_params)?;
549                self.apply_type_bindings_to_block(body, bindings, type_params)
550            }
551            Stmt::While { condition, body } => {
552                self.apply_type_bindings_to_expr(condition, bindings, type_params)?;
553                self.apply_type_bindings_to_block(body, bindings, type_params)
554            }
555            Stmt::Match { value, arms } => {
556                self.apply_type_bindings_to_expr(value, bindings, type_params)?;
557                for arm in arms {
558                    self.apply_type_bindings_to_block(&mut arm.body, bindings, type_params)?;
559                }
560                Ok(())
561            }
562            Stmt::Meta { .. } => Ok(()),
563        }
564    }
565
566    pub(super) fn apply_type_bindings_to_expr(
567        &mut self,
568        expr: &mut Expr,
569        bindings: &BTreeMap<String, Ty>,
570        type_params: &BTreeSet<String>,
571    ) -> Result<(), ElabError> {
572        match expr {
573            Expr::Call { callee, args, .. } => {
574                self.apply_type_bindings_to_expr(callee, bindings, type_params)?;
575                for arg in args {
576                    self.apply_type_bindings_to_call_arg(arg, bindings, type_params)?;
577                }
578                Ok(())
579            }
580            Expr::IntrinsicCall { args, .. } => {
581                for arg in args {
582                    self.apply_type_bindings_to_call_arg(arg, bindings, type_params)?;
583                }
584                Ok(())
585            }
586            Expr::Field { base, .. } | Expr::Prefix { value: base, .. } => {
587                self.apply_type_bindings_to_expr(base, bindings, type_params)
588            }
589            Expr::Index { base, index } => {
590                self.apply_type_bindings_to_expr(base, bindings, type_params)?;
591                self.apply_type_bindings_to_expr(index, bindings, type_params)
592            }
593            Expr::SliceRange { base, start, end } => {
594                self.apply_type_bindings_to_expr(base, bindings, type_params)?;
595                if let Some(start) = start {
596                    self.apply_type_bindings_to_expr(start, bindings, type_params)?;
597                }
598                if let Some(end) = end {
599                    self.apply_type_bindings_to_expr(end, bindings, type_params)?;
600                }
601                Ok(())
602            }
603            Expr::Binary { lhs, rhs, .. } => {
604                self.apply_type_bindings_to_expr(lhs, bindings, type_params)?;
605                self.apply_type_bindings_to_expr(rhs, bindings, type_params)
606            }
607            Expr::Relational { lhs, rhs, .. } => {
608                self.apply_type_bindings_to_expr(lhs, bindings, type_params)?;
609                self.apply_type_bindings_to_expr(rhs, bindings, type_params)
610            }
611            Expr::Array { items, .. } => {
612                for item in items {
613                    self.apply_type_bindings_to_expr(item, bindings, type_params)?;
614                }
615                Ok(())
616            }
617            Expr::Tuple { items, .. } => {
618                for item in items {
619                    self.apply_type_bindings_to_expr(item, bindings, type_params)?;
620                }
621                Ok(())
622            }
623            Expr::StructLit { fields, .. } => {
624                for field in fields {
625                    self.apply_type_bindings_to_expr(&mut field.value, bindings, type_params)?;
626                }
627                Ok(())
628            }
629            Expr::Block(block) => self.apply_type_bindings_to_block(block, bindings, type_params),
630            Expr::Ident { .. }
631            | Expr::Int(_)
632            | Expr::Number(_)
633            | Expr::String(_)
634            | Expr::Bool(_)
635            | Expr::Splice(_) => Ok(()),
636        }
637    }
638
639    pub(super) fn apply_type_bindings_to_call_arg(
640        &mut self,
641        arg: &mut CallArg,
642        bindings: &BTreeMap<String, Ty>,
643        type_params: &BTreeSet<String>,
644    ) -> Result<(), ElabError> {
645        match arg {
646            CallArg::Expr(expr) | CallArg::Spread(expr) => {
647                self.apply_type_bindings_to_expr(expr, bindings, type_params)
648            }
649            CallArg::Type(ty) => {
650                let resolved = self.resolve_type_expr(ty, bindings, type_params, None)?;
651                self.ensure_ty_instantiated(&resolved)?;
652                *ty = ty_to_type_expr(&resolved);
653                Ok(())
654            }
655        }
656    }
657
658    pub(super) fn apply_type_bindings_to_type_ref(
659        &mut self,
660        ty: &mut TypeRef,
661        bindings: &BTreeMap<String, Ty>,
662        type_params: &BTreeSet<String>,
663    ) -> Result<(), ElabError> {
664        let resolved = self.resolve_type_expr(&ty.ty, bindings, type_params, None)?;
665        self.ensure_ty_instantiated(&resolved)?;
666        ty.ty = ty_to_type_expr(&resolved);
667        Ok(())
668    }
669}