1use std::collections::{HashMap, HashSet};
17
18use crate::analysis::unify::{InferType, TyVar, TypeScope};
19use crate::analysis::{
20 infer_instantiations, FieldDef, FieldType, Instantiations, Site, TypeDef, TypeRegistry,
21 VariantDef,
22};
23use crate::ast::stmt::{Expr, MatchArm, Stmt, TypeExpr};
24use crate::ast_map::{self, Arenas, AstMap};
25use crate::intern::{Interner, Symbol};
26
27const INSTANCE_BUDGET: usize = 4096;
30
31#[derive(Clone, Copy, Debug)]
33pub struct Options {
34 pub lower_option: bool,
36}
37
38#[derive(Clone, Debug)]
40pub struct TypeInstance {
41 pub generic: Symbol,
42 pub args: Vec<InferType>,
43}
44
45pub struct Monomorphized<'a> {
48 pub stmts: Vec<Stmt<'a>>,
49 pub registry: TypeRegistry,
50 pub instances: HashMap<Symbol, TypeInstance>,
51}
52
53pub fn monomorphize<'a>(
56 stmts: &[Stmt<'a>],
57 registry: &TypeRegistry,
58 interner: &mut Interner,
59 arenas: Arenas<'a>,
60 options: Options,
61) -> Result<Monomorphized<'a>, String> {
62 let inst = infer_instantiations(stmts, interner, registry);
63 let generic_fns: HashMap<Symbol, &Stmt<'a>> = stmts
64 .iter()
65 .filter_map(|s| match s {
66 Stmt::FunctionDef { name, generics, .. } if !generics.is_empty() => Some((*name, s)),
67 _ => None,
68 })
69 .collect();
70 if !needs_monomorphization(stmts, registry, interner, &inst, options) {
71 return Ok(Monomorphized {
72 stmts: stmts.to_vec(),
73 registry: registry.clone(),
74 instances: HashMap::new(),
75 });
76 }
77
78 let mut taken: HashSet<String> = registry
79 .iter_types()
80 .map(|(s, _)| interner.resolve(*s).to_string())
81 .collect();
82 for s in stmts {
83 if let Stmt::FunctionDef { name, .. } = s {
84 taken.insert(interner.resolve(*name).to_string());
85 }
86 }
87 let twins = registry.namespaced_twins(interner);
88 let mut mono = Mono {
89 arenas,
90 registry,
91 inst: &inst,
92 options,
93 twins,
94 interner,
95 generic_fns,
96 taken,
97 fn_instances: HashMap::new(),
98 pending: std::collections::VecDeque::new(),
99 instances_of: HashMap::new(),
100 type_instances: HashMap::new(),
101 out_registry: registry.clone(),
102 instance_info: HashMap::new(),
103 subst: HashMap::new(),
104 param_types: HashMap::new(),
105 error: None,
106 };
107
108 enum Segment<'a> {
109 Stmt(Stmt<'a>),
110 InstancesOf(Symbol),
111 }
112 let mut segments = Vec::with_capacity(stmts.len());
113 for s in stmts {
114 match s {
115 Stmt::FunctionDef { name, generics, .. } if !generics.is_empty() => {
116 segments.push(Segment::InstancesOf(*name))
117 }
118 _ => segments.push(Segment::Stmt(mono.map_stmt(s))),
119 }
120 }
121 while let Some((generic, args, name)) = mono.pending.pop_front() {
122 let def = mono.instantiate_function(generic, &args, name);
123 mono.instances_of.entry(generic).or_default().push(def);
124 }
125 if let Some(e) = mono.error.take() {
126 return Err(e);
127 }
128
129 let mut out = Vec::with_capacity(segments.len());
130 for seg in segments {
131 match seg {
132 Segment::Stmt(s) => out.push(s),
133 Segment::InstancesOf(f) => out.extend(mono.instances_of.remove(&f).unwrap_or_default()),
134 }
135 }
136 Ok(Monomorphized {
137 stmts: out,
138 registry: mono.out_registry,
139 instances: mono.instance_info,
140 })
141}
142
143fn needs_monomorphization(
147 stmts: &[Stmt],
148 registry: &TypeRegistry,
149 interner: &Interner,
150 inst: &Instantiations,
151 options: Options,
152) -> bool {
153 let generic_type = |t: &InferType| mentions_generic(t, options);
154 if !inst.calls.is_empty() {
155 return true;
156 }
157 if inst.constructed.values().any(generic_type)
158 || inst.empty_lists.values().any(is_retyped_empty_list)
159 {
160 return true;
161 }
162 if inst.scrutinees.values().any(generic_type) {
163 return true;
164 }
165 let empty = HashMap::new();
166 let twins = registry.namespaced_twins(interner);
167 let scope = TypeScope {
168 interner,
169 registry: Some(registry),
170 params: &empty,
171 twins: Some(&twins),
172 };
173 stmts.iter().any(|s| match s {
174 Stmt::FunctionDef {
175 params,
176 return_type,
177 ..
178 } => params
179 .iter()
180 .map(|(_, t)| *t)
181 .chain(return_type.iter().copied())
182 .any(|t| generic_type(&InferType::from_type_expr_in(t, &scope))),
183 _ => false,
184 })
185}
186
187fn mentions_generic(t: &InferType, options: Options) -> bool {
188 let rec = |x: &InferType| mentions_generic(x, options);
189 match t {
190 InferType::UserDefined(_, args) => !args.is_empty() || args.iter().any(rec),
191 InferType::Option(inner) => options.lower_option || rec(inner),
192 InferType::Seq(i) | InferType::Set(i) => rec(i),
193 InferType::Map(k, v) => rec(k) || rec(v),
194 InferType::Function(ps, r) => ps.iter().any(rec) || rec(r),
195 _ => false,
196 }
197}
198
199fn is_retyped_empty_list(t: &InferType) -> bool {
202 matches!(t, InferType::Seq(elem) if !matches!(**elem, InferType::Int | InferType::Var(_) | InferType::Unknown))
203}
204
205struct Mono<'a, 'r> {
206 arenas: Arenas<'a>,
207 registry: &'r TypeRegistry,
208 inst: &'r Instantiations,
209 options: Options,
210 interner: &'r mut Interner,
211 generic_fns: HashMap<Symbol, &'r Stmt<'a>>,
212 taken: HashSet<String>,
214 fn_instances: HashMap<(Symbol, String), Symbol>,
215 pending: std::collections::VecDeque<(Symbol, Vec<InferType>, Symbol)>,
216 instances_of: HashMap<Symbol, Vec<Stmt<'a>>>,
217 type_instances: HashMap<(Symbol, String), Symbol>,
218 out_registry: TypeRegistry,
219 instance_info: HashMap<Symbol, TypeInstance>,
220 subst: HashMap<TyVar, InferType>,
223 param_types: HashMap<Symbol, InferType>,
224 error: Option<String>,
225 twins: HashMap<Symbol, Symbol>,
227}
228
229fn key_of(types: &[InferType]) -> String {
231 format!("{types:?}")
232}
233
234impl<'a, 'r> Mono<'a, 'r> {
235 fn fail(&mut self, message: String) {
236 if self.error.is_none() {
237 self.error = Some(message);
238 }
239 }
240
241 fn sym(&mut self, name: &str) -> Symbol {
242 self.interner.intern(name)
243 }
244
245 fn mint(&mut self, parts: &str) -> Symbol {
247 let base: String = parts
248 .chars()
249 .map(|c| {
250 if c.is_ascii_alphanumeric() || c == '_' {
251 c
252 } else {
253 '_'
254 }
255 })
256 .collect();
257 let mut name = base.clone();
258 let mut n = 2;
259 while self.taken.contains(&name) {
260 name = format!("{base}_{n}");
261 n += 1;
262 }
263 self.taken.insert(name.clone());
264 self.interner.intern(&name)
265 }
266
267 fn ground(&self, t: &InferType) -> Result<InferType, String> {
271 Ok(match t {
272 InferType::Var(tv) => self.subst.get(tv).cloned().unwrap_or(InferType::Int),
273 InferType::Unknown => return Err("a type the checker could not determine".to_string()),
274 InferType::Seq(i) => InferType::Seq(Box::new(self.ground(i)?)),
275 InferType::Set(i) => InferType::Set(Box::new(self.ground(i)?)),
276 InferType::Option(i) => InferType::Option(Box::new(self.ground(i)?)),
277 InferType::Map(k, v) => {
278 InferType::Map(Box::new(self.ground(k)?), Box::new(self.ground(v)?))
279 }
280 InferType::UserDefined(s, args) => InferType::UserDefined(
281 *s,
282 args.iter()
283 .map(|a| self.ground(a))
284 .collect::<Result<_, _>>()?,
285 ),
286 InferType::Function(ps, r) => InferType::Function(
287 ps.iter()
288 .map(|p| self.ground(p))
289 .collect::<Result<_, _>>()?,
290 Box::new(self.ground(r)?),
291 ),
292 ground => ground.clone(),
293 })
294 }
295
296 fn leaves_open(&self, t: &InferType) -> bool {
298 match t {
299 InferType::Var(tv) => !self.subst.contains_key(tv),
300 InferType::Seq(i) | InferType::Set(i) | InferType::Option(i) => self.leaves_open(i),
301 InferType::Map(k, v) => self.leaves_open(k) || self.leaves_open(v),
302 InferType::UserDefined(_, args) => args.iter().any(|a| self.leaves_open(a)),
303 InferType::Function(ps, r) => {
304 ps.iter().any(|p| self.leaves_open(p)) || self.leaves_open(r)
305 }
306 _ => false,
307 }
308 }
309
310 fn name_part(&mut self, t: &InferType) -> String {
311 match t {
312 InferType::Int => "Int".into(),
313 InferType::Float => "Real".into(),
314 InferType::String => "Text".into(),
315 InferType::Bool => "Bool".into(),
316 InferType::Seq(i) => format!("Seq_{}", self.name_part(i)),
317 InferType::Set(i) => format!("Set_{}", self.name_part(i)),
318 InferType::Option(i) => format!("Option_{}", self.name_part(i)),
319 InferType::Map(k, v) => format!("Map_{}_{}", self.name_part(k), self.name_part(v)),
320 InferType::UserDefined(s, args) if args.is_empty() => {
321 self.interner.resolve(*s).to_string()
322 }
323 InferType::UserDefined(s, args) => {
324 let parts: Vec<String> = args.iter().map(|a| self.name_part(a)).collect();
325 format!("{}_{}", self.interner.resolve(*s), parts.join("_"))
326 }
327 InferType::Function(ps, r) => {
328 let parts: Vec<String> = ps.iter().map(|p| self.name_part(p)).collect();
329 format!("Fn_{}_to_{}", parts.join("_"), self.name_part(r))
330 }
331 other => other.to_logos_name(),
332 }
333 }
334
335 fn call_instance(&mut self, f: Symbol, site: Site) -> Option<Symbol> {
338 let fname = self.interner.resolve(f).to_string();
339 let Some(call) = self.inst.calls.get(&site).cloned() else {
340 self.fail(format!("the call of the generic function `{fname}` could not be type-checked, so its type arguments are unknown"));
341 return None;
342 };
343 if !call.precise && call.type_args.iter().any(|t| self.leaves_open(t)) {
344 self.fail(format!(
345 "cannot determine the type arguments of this call of `{fname}`: an argument's type is not known before running the program"
346 ));
347 return None;
348 }
349 let mut args = Vec::with_capacity(call.type_args.len());
350 for t in &call.type_args {
351 match self.ground(t) {
352 Ok(g) => args.push(g),
353 Err(why) => {
354 self.fail(format!("cannot instantiate `{fname}`: {why}"));
355 return None;
356 }
357 }
358 }
359 let key = (f, key_of(&args));
360 if let Some(name) = self.fn_instances.get(&key) {
361 return Some(*name);
362 }
363 if self.fn_instances.len() + self.type_instances.len() >= INSTANCE_BUDGET {
364 self.fail(format!(
365 "`{fname}` needs more than {INSTANCE_BUDGET} concrete copies — it calls itself at an ever-larger type, which a tier without generics cannot compile"
366 ));
367 return None;
368 }
369 let parts: Vec<String> = args.iter().map(|a| self.name_part(a)).collect();
370 let name = self.mint(&format!("{fname}__{}", parts.join("__")));
371 self.fn_instances.insert(key, name);
372 self.pending.push_back((f, args, name));
373 Some(name)
374 }
375
376 fn template(&mut self, generic: Symbol) -> Option<TypeDef> {
383 if let Some(def @ (TypeDef::Struct { .. } | TypeDef::Enum { .. })) =
384 self.registry.get(generic)
385 {
386 return Some(def.clone());
387 }
388 if self.interner.resolve(generic) != "Option" {
389 return None;
390 }
391 let t = self.sym("T");
392 let (some, none, value) = (self.sym("Some"), self.sym("None"), self.sym("value"));
393 Some(TypeDef::Enum {
394 variants: vec![
395 VariantDef {
396 name: some,
397 fields: vec![FieldDef {
398 name: value,
399 ty: FieldType::TypeParam(t),
400 is_public: true,
401 }],
402 },
403 VariantDef {
404 name: none,
405 fields: Vec::new(),
406 },
407 ],
408 generics: vec![t],
409 is_portable: false,
410 is_shared: false,
411 })
412 }
413
414 fn type_instance(&mut self, t: &InferType) -> Option<Symbol> {
417 let (generic, args) = match t {
418 InferType::UserDefined(g, args) if !args.is_empty() => (*g, args.clone()),
419 InferType::Option(inner) if self.options.lower_option => {
420 (self.sym("Option"), vec![(**inner).clone()])
421 }
422 _ => return None,
423 };
424 let key = (generic, key_of(&args));
425 if let Some(name) = self.type_instances.get(&key) {
426 return Some(*name);
427 }
428 if self.fn_instances.len() + self.type_instances.len() >= INSTANCE_BUDGET {
429 let gname = self.interner.resolve(generic).to_string();
430 self.fail(format!(
431 "`{gname}` needs more than {INSTANCE_BUDGET} concrete types"
432 ));
433 return None;
434 }
435 let parts: Vec<String> = args.iter().map(|a| self.name_part(a)).collect();
436 let gname = self.interner.resolve(generic).to_string();
437 let name = self.mint(&format!("{gname}__{}", parts.join("__")));
438 self.type_instances.insert(key, name);
439 self.instance_info.insert(
440 name,
441 TypeInstance {
442 generic,
443 args: args.clone(),
444 },
445 );
446 let def = match self.template(generic) {
447 Some(TypeDef::Struct {
448 fields,
449 generics,
450 is_portable,
451 is_shared,
452 }) => {
453 let params: HashMap<Symbol, InferType> =
454 generics.iter().copied().zip(args.iter().cloned()).collect();
455 let fields = fields
456 .iter()
457 .map(|f| FieldDef {
458 name: f.name,
459 ty: self.field_type(&f.ty, ¶ms),
460 is_public: f.is_public,
461 })
462 .collect();
463 TypeDef::Struct {
464 fields,
465 generics: Vec::new(),
466 is_portable,
467 is_shared,
468 }
469 }
470 Some(TypeDef::Enum {
471 variants,
472 generics,
473 is_portable,
474 is_shared,
475 }) => {
476 let params: HashMap<Symbol, InferType> =
477 generics.iter().copied().zip(args.iter().cloned()).collect();
478 let variants = variants
479 .iter()
480 .map(|v| VariantDef {
481 name: v.name,
482 fields: v
483 .fields
484 .iter()
485 .map(|f| FieldDef {
486 name: f.name,
487 ty: self.field_type(&f.ty, ¶ms),
488 is_public: f.is_public,
489 })
490 .collect(),
491 })
492 .collect();
493 TypeDef::Enum {
494 variants,
495 generics: Vec::new(),
496 is_portable,
497 is_shared,
498 }
499 }
500 _ => {
501 self.fail(format!(
502 "`{gname}` is applied to type arguments but is not a generic record or enum"
503 ));
504 return None;
505 }
506 };
507 self.out_registry.register(name, def);
508 Some(name)
509 }
510
511 fn field_type(&mut self, ft: &FieldType, params: &HashMap<Symbol, InferType>) -> FieldType {
515 if !self.field_mentions(ft, params) {
516 return ft.clone();
517 }
518 match ft {
520 FieldType::Tuple(items) => {
521 return FieldType::Tuple(items.iter().map(|t| self.field_type(t, params)).collect())
522 }
523 FieldType::Record(fields) => {
524 return FieldType::Record(
525 fields
526 .iter()
527 .map(|(n, t)| (*n, self.field_type(t, params)))
528 .collect(),
529 )
530 }
531 _ => {}
532 }
533 let ty = InferType::from_field_type_in(
534 ft,
535 &TypeScope {
536 interner: self.interner,
537 registry: Some(self.registry),
538 params,
539 twins: Some(&self.twins),
540 },
541 );
542 match self.ground(&ty) {
543 Ok(g) => self.ground_field_type(&g),
544 Err(why) => {
545 self.fail(format!("cannot lay out a field: {why}"));
546 ft.clone()
547 }
548 }
549 }
550
551 fn field_mentions(&self, ft: &FieldType, params: &HashMap<Symbol, InferType>) -> bool {
552 match ft {
553 FieldType::TypeParam(p) | FieldType::Named(p) => params.contains_key(p),
554 FieldType::Primitive(_) => false,
555 FieldType::Generic { base, params: ps } => {
556 self.is_generic_type(*base) || ps.iter().any(|p| self.field_mentions(p, params))
557 }
558 FieldType::Tuple(items) => items.iter().any(|t| self.field_mentions(t, params)),
559 FieldType::Record(fields) => fields.iter().any(|(_, t)| self.field_mentions(t, params)),
560 }
561 }
562
563 fn is_generic_type(&self, base: Symbol) -> bool {
565 match self.registry.get(base) {
566 Some(TypeDef::Struct { generics, .. } | TypeDef::Enum { generics, .. }) => {
567 !generics.is_empty()
568 }
569 _ => false,
570 }
571 }
572
573 fn ground_field_type(&mut self, t: &InferType) -> FieldType {
574 if let Some(inst) = self.type_instance(t) {
575 return FieldType::Named(inst);
576 }
577 match t {
578 InferType::Seq(i) => FieldType::Generic {
579 base: self.sym("Seq"),
580 params: vec![self.ground_field_type(i)],
581 },
582 InferType::Set(i) => FieldType::Generic {
583 base: self.sym("Set"),
584 params: vec![self.ground_field_type(i)],
585 },
586 InferType::Option(i) => FieldType::Generic {
587 base: self.sym("Option"),
588 params: vec![self.ground_field_type(i)],
589 },
590 InferType::Map(k, v) => FieldType::Generic {
591 base: self.sym("Map"),
592 params: vec![self.ground_field_type(k), self.ground_field_type(v)],
593 },
594 InferType::UserDefined(s, _) => FieldType::Named(*s),
595 other => match other.primitive_name() {
596 Some(name) => FieldType::Primitive(self.sym(name)),
597 None => {
598 let shown = other.to_logos_name();
599 self.fail(format!("a record field cannot hold a {shown} on this tier"));
600 FieldType::Primitive(self.sym("Int"))
601 }
602 },
603 }
604 }
605
606 fn ground_type_expr(&mut self, t: &InferType) -> TypeExpr<'a> {
608 if let Some(inst) = self.type_instance(t) {
609 return TypeExpr::Named(inst);
610 }
611 let types = self.arenas.types;
612 match t {
613 InferType::Seq(i) => {
614 let p = self.ground_type_expr(i);
615 TypeExpr::Generic {
616 base: self.sym("Seq"),
617 params: types.alloc_slice([p]),
618 }
619 }
620 InferType::Set(i) => {
621 let p = self.ground_type_expr(i);
622 TypeExpr::Generic {
623 base: self.sym("Set"),
624 params: types.alloc_slice([p]),
625 }
626 }
627 InferType::Option(i) => {
628 let p = self.ground_type_expr(i);
629 TypeExpr::Generic {
630 base: self.sym("Option"),
631 params: types.alloc_slice([p]),
632 }
633 }
634 InferType::Map(k, v) => {
635 let (k, v) = (self.ground_type_expr(k), self.ground_type_expr(v));
636 TypeExpr::Generic {
637 base: self.sym("Map"),
638 params: types.alloc_slice([k, v]),
639 }
640 }
641 InferType::Function(ps, r) => {
642 let inputs: Vec<TypeExpr<'a>> =
643 ps.iter().map(|p| self.ground_type_expr(p)).collect();
644 let output = self.ground_type_expr(r);
645 TypeExpr::Function {
646 inputs: types.alloc_slice(inputs),
647 output: types.alloc(output),
648 }
649 }
650 InferType::UserDefined(s, _) => TypeExpr::Named(*s),
651 other => match other.primitive_name() {
652 Some(name) => TypeExpr::Primitive(self.sym(name)),
653 None => {
654 let shown = other.to_logos_name();
655 self.fail(format!(
656 "a {shown} cannot be written as a type on this tier"
657 ));
658 TypeExpr::Primitive(self.sym("Int"))
659 }
660 },
661 }
662 }
663
664 fn type_mentions(&self, t: &TypeExpr) -> bool {
666 match t {
667 TypeExpr::Primitive(s) | TypeExpr::Named(s) => self.param_types.contains_key(s),
668 TypeExpr::Generic { base, params } => {
669 self.is_generic_type(*base)
670 || (self.options.lower_option && self.is_option_name(*base))
671 || params.iter().any(|p| self.type_mentions(p))
672 }
673 TypeExpr::Tuple(items) => items.iter().any(|p| self.type_mentions(p)),
674 TypeExpr::Record { field_types, .. } => {
675 field_types.iter().any(|p| self.type_mentions(p))
676 }
677 TypeExpr::Function { inputs, output } => {
678 inputs.iter().any(|p| self.type_mentions(p)) || self.type_mentions(output)
679 }
680 TypeExpr::Refinement { base, .. } => self.type_mentions(base),
681 TypeExpr::Persistent { inner } | TypeExpr::Mutable { inner } => {
682 self.type_mentions(inner)
683 }
684 }
685 }
686
687 fn is_option_name(&self, base: Symbol) -> bool {
688 let name = self.interner.resolve(base);
689 name == "Option"
690 || (name == "Maybe"
691 && !matches!(
692 self.registry.get(base),
693 Some(TypeDef::Struct { .. } | TypeDef::Enum { .. })
694 ))
695 }
696
697 fn instantiate_function(
699 &mut self,
700 generic: Symbol,
701 args: &[InferType],
702 name: Symbol,
703 ) -> Stmt<'a> {
704 let def = self.generic_fns[&generic];
705 let Stmt::FunctionDef {
706 params,
707 body,
708 return_type,
709 is_native,
710 native_path,
711 is_exported,
712 export_target,
713 opt_flags,
714 ..
715 } = def
716 else {
717 unreachable!("generic_fns holds function definitions only")
718 };
719 let declared = self
720 .inst
721 .type_params
722 .get(&generic)
723 .cloned()
724 .unwrap_or_default();
725 let saved_subst = std::mem::take(&mut self.subst);
726 let saved_params = std::mem::take(&mut self.param_types);
727 for ((param, resolved), arg) in declared.iter().zip(args) {
728 if let InferType::Var(tv) = resolved {
729 self.subst.insert(*tv, arg.clone());
730 }
731 self.param_types.insert(*param, arg.clone());
732 }
733 let params = params.iter().map(|(p, t)| (*p, self.map_type(t))).collect();
734 let return_type = return_type.map(|t| self.map_type(t));
735 let body = self.map_block(body);
736 self.subst = saved_subst;
737 self.param_types = saved_params;
738 Stmt::FunctionDef {
739 name,
740 generics: Vec::new(),
741 params,
742 body,
743 return_type,
744 is_native: *is_native,
745 native_path: *native_path,
746 is_exported: *is_exported,
747 export_target: *export_target,
748 opt_flags: *opt_flags,
749 }
750 }
751
752 fn fields_by_position(
756 &self,
757 inst: Symbol,
758 variant: Symbol,
759 bindings: &[(Symbol, Symbol)],
760 ) -> Vec<(Symbol, Symbol)> {
761 let fields: Vec<Symbol> = match self.out_registry.get(inst) {
762 Some(TypeDef::Enum { variants, .. }) => variants
763 .iter()
764 .find(|v| v.name == variant)
765 .map(|v| v.fields.iter().map(|f| f.name).collect())
766 .unwrap_or_default(),
767 _ => Vec::new(),
768 };
769 bindings
770 .iter()
771 .enumerate()
772 .map(|(i, (field, binding))| match fields.get(i) {
773 Some(declared) if !fields.contains(field) => (*declared, *binding),
774 _ => (*field, *binding),
775 })
776 .collect()
777 }
778
779 fn site_instance(&mut self, recorded: Option<&InferType>, what: &str) -> Option<Symbol> {
781 let recorded = recorded?.clone();
782 match self.ground(&recorded) {
783 Ok(g) => self.type_instance(&g),
784 Err(why) => {
785 self.fail(format!("cannot instantiate {what}: {why}"));
786 None
787 }
788 }
789 }
790}
791
792impl<'a, 'r> AstMap<'a> for Mono<'a, 'r> {
793 fn arenas(&self) -> Arenas<'a> {
794 self.arenas
795 }
796
797 fn map_type(&mut self, t: &'a TypeExpr<'a>) -> &'a TypeExpr<'a> {
798 if !self.type_mentions(t) {
799 return t;
800 }
801 match t {
802 TypeExpr::Primitive(s) | TypeExpr::Named(s) if self.param_types.contains_key(s) => {
803 let g = self.param_types[s].clone();
804 let written = self.ground_type_expr(&g);
805 self.arenas.types.alloc(written)
806 }
807 TypeExpr::Generic { base, .. }
808 if self.is_generic_type(*base)
809 || (self.options.lower_option && self.is_option_name(*base)) =>
810 {
811 let params = self.param_types.clone();
812 let ty = InferType::from_type_expr_in(
813 t,
814 &TypeScope {
815 interner: self.interner,
816 registry: Some(self.registry),
817 params: ¶ms,
818 twins: Some(&self.twins),
819 },
820 );
821 match self.ground(&ty) {
822 Ok(g) => {
823 let written = self.ground_type_expr(&g);
824 self.arenas.types.alloc(written)
825 }
826 Err(why) => {
827 self.fail(format!("cannot instantiate a written type: {why}"));
828 t
829 }
830 }
831 }
832 _ => ast_map::walk_type(self, t),
833 }
834 }
835
836 fn map_expr(&mut self, e: &'a Expr<'a>) -> &'a Expr<'a> {
837 let site = Site::of_expr(e);
838 let exprs = self.arenas.exprs;
839 let mapped = match e {
840 Expr::Call { function, args } if self.generic_fns.contains_key(function) => {
841 let function = self.call_instance(*function, site).unwrap_or(*function);
842 let args = args.iter().map(|a| self.map_expr(a)).collect();
843 exprs.alloc(Expr::Call { function, args })
844 }
845 Expr::New {
846 type_name,
847 init_fields,
848 ..
849 } if self.is_generic_type(*type_name) => {
850 let what = format!("a new {}", self.interner.resolve(*type_name));
851 let recorded = self.inst.constructed.get(&site).cloned();
852 let type_name = self
853 .site_instance(recorded.as_ref(), &what)
854 .unwrap_or(*type_name);
855 let init_fields = init_fields
856 .iter()
857 .map(|(f, v)| (*f, self.map_expr(v)))
858 .collect();
859 exprs.alloc(Expr::New {
860 type_name,
861 type_args: Vec::new(),
862 init_fields,
863 })
864 }
865 Expr::NewVariant {
866 enum_name,
867 variant,
868 fields,
869 } if self.is_generic_type(*enum_name) => {
870 let what = format!("a new {}", self.interner.resolve(*variant));
871 let recorded = self.inst.constructed.get(&site).cloned();
872 let enum_name = self
873 .site_instance(recorded.as_ref(), &what)
874 .unwrap_or(*enum_name);
875 let fields = fields.iter().map(|(f, v)| (*f, self.map_expr(v))).collect();
876 exprs.alloc(Expr::NewVariant {
877 enum_name,
878 variant: *variant,
879 fields,
880 })
881 }
882 Expr::OptionSome { value } if self.options.lower_option => {
883 let recorded = self.inst.constructed.get(&site).cloned();
884 let value = self.map_expr(value);
885 match self.site_instance(recorded.as_ref(), "`some`") {
886 Some(enum_name) => {
887 let (variant, field) = (self.sym("Some"), self.sym("value"));
888 exprs.alloc(Expr::NewVariant {
889 enum_name,
890 variant,
891 fields: vec![(field, value)],
892 })
893 }
894 None => exprs.alloc(Expr::OptionSome { value }),
895 }
896 }
897 Expr::OptionNone if self.options.lower_option => {
898 let recorded = self.inst.constructed.get(&site).cloned();
899 match self.site_instance(recorded.as_ref(), "`none`") {
900 Some(enum_name) => {
901 let variant = self.sym("None");
902 exprs.alloc(Expr::NewVariant {
903 enum_name,
904 variant,
905 fields: Vec::new(),
906 })
907 }
908 None => e,
909 }
910 }
911 Expr::List(items) if items.is_empty() => {
912 let recorded = self.inst.empty_lists.get(&site).cloned();
913 let elem = match recorded.map(|t| self.ground(&t)) {
914 Some(Ok(InferType::Seq(elem)))
915 if is_retyped_empty_list(&InferType::Seq(elem.clone())) =>
916 {
917 *elem
918 }
919 _ => return preserve_expr_facts(e, e),
920 };
921 let written = self.ground_type_expr(&elem);
922 let seq = self.sym("Seq");
923 exprs.alloc(Expr::New {
924 type_name: seq,
925 type_args: vec![written],
926 init_fields: Vec::new(),
927 })
928 }
929 _ => ast_map::walk_expr(self, e),
930 };
931 preserve_expr_facts(e, mapped)
932 }
933
934 fn map_stmt(&mut self, s: &Stmt<'a>) -> Stmt<'a> {
935 match s {
936 Stmt::Call { function, args } if self.generic_fns.contains_key(function) => {
937 let function = self
938 .call_instance(*function, Site::of_stmt(s))
939 .unwrap_or(*function);
940 Stmt::Call {
941 function,
942 args: args.iter().map(|a| self.map_expr(a)).collect(),
943 }
944 }
945 Stmt::LaunchTask { function, .. } | Stmt::LaunchTaskWithHandle { function, .. }
946 if self.generic_fns.contains_key(function) =>
947 {
948 let fname = self.interner.resolve(*function).to_string();
949 self.fail(format!(
950 "the generic function `{fname}` cannot be launched as a task on this tier"
951 ));
952 ast_map::walk_stmt(self, s)
953 }
954 Stmt::Inspect {
955 target,
956 arms,
957 has_otherwise,
958 } => {
959 let recorded = self.inst.scrutinees.get(&Site::of_stmt(s)).cloned();
960 let instance = self.site_instance(recorded.as_ref(), "an inspected value");
961 let target = self.map_expr(target);
962 let arms = arms
963 .iter()
964 .map(|a| {
965 let mapped = self.map_arm(a);
966 match (instance, mapped.variant) {
967 (Some(inst), Some(variant)) => {
968 let bindings =
969 self.fields_by_position(inst, variant, &mapped.bindings);
970 MatchArm {
971 enum_name: Some(inst),
972 bindings,
973 ..mapped
974 }
975 }
976 _ => mapped,
977 }
978 })
979 .collect();
980 Stmt::Inspect {
981 target,
982 arms,
983 has_otherwise: *has_otherwise,
984 }
985 }
986 _ => ast_map::walk_stmt(self, s),
987 }
988 }
989}
990
991fn preserve_expr_facts<'a>(from: &Expr<'a>, to: &'a Expr<'a>) -> &'a Expr<'a> {
995 use crate::optimize::facts::{self, Fact};
996
997 let had_tile_fact = facts::holds_expr(Fact::TileLegal, from);
998 facts::copy_expr_facts(from, to);
999 if had_tile_fact && std::env::var_os("LOGOS_DEBUG_C_TILE").is_some() {
1000 eprintln!("C TileLegal handoff: {:p} -> {:p}", from, to);
1001 }
1002 to
1003}
1004
1005#[cfg(test)]
1006#[path = "../../logicaffeine_tests/unit/logicaffeine_compile/monomorphize/tests.rs"]
1007mod tests;