1mod expr_checker;
2mod item_checker;
3mod stmt_checker;
4mod type_env;
5use crate::modules::{LoadedModule, ModuleImports};
6use crate::{
7 ast::*,
8 config::LustConfig,
9 error::{LustError, Result},
10};
11pub(super) use alloc::{
12 boxed::Box,
13 format,
14 string::{String, ToString},
15 vec::Vec,
16};
17use core::mem;
18use hashbrown::{HashMap, HashSet};
19pub use type_env::FunctionSignature;
20pub use type_env::TypeEnv;
21pub struct TypeChecker {
22 env: TypeEnv,
23 current_function_return_type: Option<Type>,
24 in_loop: bool,
25 pending_generic_instances: Option<HashMap<String, Type>>,
26 expected_lambda_signature: Option<(Vec<Type>, Option<Type>)>,
27 current_trait_bounds: HashMap<String, Vec<String>>,
28 current_module: Option<String>,
29 imports_by_module: HashMap<String, ModuleImports>,
30 expr_types_by_module: HashMap<String, HashMap<Span, Type>>,
31 variable_types_by_module: HashMap<String, HashMap<Span, Type>>,
32}
33
34pub struct TypeCollection {
35 pub expr_types: HashMap<String, HashMap<Span, Type>>,
36 pub variable_types: HashMap<String, HashMap<Span, Type>>,
37}
38
39impl TypeChecker {
40 pub fn new() -> Self {
41 Self::with_config(&LustConfig::default())
42 }
43
44 pub fn with_config(config: &LustConfig) -> Self {
45 Self {
46 env: TypeEnv::with_config(config),
47 current_function_return_type: None,
48 in_loop: false,
49 pending_generic_instances: None,
50 expected_lambda_signature: None,
51 current_trait_bounds: HashMap::new(),
52 current_module: None,
53 imports_by_module: HashMap::new(),
54 expr_types_by_module: HashMap::new(),
55 variable_types_by_module: HashMap::new(),
56 }
57 }
58
59 fn dummy_span() -> Span {
60 Span::new(0, 0, 0, 0)
61 }
62
63 pub fn check_module(&mut self, items: &[Item]) -> Result<()> {
64 for item in items {
65 self.register_type_definition(item)?;
66 }
67
68 self.validate_struct_cycles()?;
69 self.env.push_scope();
70 self.register_module_init_locals(items)?;
71 for item in items {
72 self.check_item(item)?;
73 }
74
75 self.env.pop_scope();
76 Ok(())
77 }
78
79 pub fn check_program(&mut self, modules: &[LoadedModule]) -> Result<()> {
80 for m in modules {
81 self.current_module = Some(m.path.clone());
82 for item in &m.items {
83 self.register_type_definition(item)?;
84 }
85 }
86
87 self.validate_struct_cycles()?;
88 for m in modules {
89 self.current_module = Some(m.path.clone());
90 self.env.push_scope();
91 self.register_module_init_locals(&m.items)?;
92 for item in &m.items {
93 self.check_item(item)?;
94 }
95
96 self.env.pop_scope();
97 }
98
99 self.current_module = None;
100 Ok(())
101 }
102
103 fn validate_struct_cycles(&self) -> Result<()> {
104 use hashbrown::{HashMap, HashSet};
105 let struct_defs = self.env.struct_definitions();
106 if struct_defs.is_empty() {
107 return Ok(());
108 }
109
110 let mut simple_to_full: HashMap<String, Vec<String>> = HashMap::new();
111 for name in struct_defs.keys() {
112 let simple = name.rsplit('.').next().unwrap_or(name).to_string();
113 simple_to_full.entry(simple).or_default().push(name.clone());
114 }
115
116 let mut struct_has_weak: HashMap<String, bool> = HashMap::new();
117 for (name, def) in &struct_defs {
118 let has_weak = def
119 .fields
120 .iter()
121 .any(|field| matches!(field.ownership, FieldOwnership::Weak));
122 struct_has_weak.insert(name.clone(), has_weak);
123 }
124
125 let mut graph: HashMap<String, Vec<String>> = HashMap::new();
126 for (name, def) in &struct_defs {
127 let module_prefix = name.rsplit_once('.').map(|(module, _)| module.to_string());
128 let mut edges: HashSet<String> = HashSet::new();
129 for field in &def.fields {
130 if matches!(field.ownership, FieldOwnership::Weak) {
131 let target = field.weak_target.as_ref().ok_or_else(|| {
132 self.type_error(format!(
133 "Field '{}.{}' is marked as 'ref' but has no target type",
134 name, field.name
135 ))
136 })?;
137 let target_name = if let TypeKind::Named(inner) = &target.kind {
138 inner
139 } else {
140 return Err(self.type_error(format!(
141 "Field '{}.{}' uses 'ref' but only struct types are supported",
142 name, field.name
143 )));
144 };
145 let resolved = self.resolve_struct_name_for_cycle(
146 target_name.as_str(),
147 module_prefix.as_deref(),
148 &struct_defs,
149 &simple_to_full,
150 );
151 if resolved.is_none() {
152 return Err(self.type_error(format!(
153 "Field '{}.{}' uses 'ref' but '{}' is not a known struct type",
154 name, field.name, target_name
155 )));
156 }
157
158 continue;
159 }
160
161 self.collect_strong_struct_targets(
162 &field.ty,
163 module_prefix.as_deref(),
164 &struct_defs,
165 &simple_to_full,
166 &mut edges,
167 );
168 }
169
170 graph.insert(name.clone(), edges.into_iter().collect());
171 }
172
173 fn dfs(
174 node: &str,
175 graph: &HashMap<String, Vec<String>>,
176 visited: &mut HashSet<String>,
177 on_stack: &mut HashSet<String>,
178 stack: &mut Vec<String>,
179 ) -> Option<Vec<String>> {
180 visited.insert(node.to_string());
181 on_stack.insert(node.to_string());
182 stack.push(node.to_string());
183 if let Some(neighbors) = graph.get(node) {
184 for neighbor in neighbors {
185 if !visited.contains(neighbor) {
186 if let Some(cycle) = dfs(neighbor, graph, visited, on_stack, stack) {
187 return Some(cycle);
188 }
189 } else if on_stack.contains(neighbor) {
190 if let Some(pos) = stack.iter().position(|n| n == neighbor) {
191 let mut cycle = stack[pos..].to_vec();
192 cycle.push(neighbor.clone());
193 return Some(cycle);
194 }
195 }
196 }
197 }
198
199 stack.pop();
200 on_stack.remove(node);
201 None
202 }
203
204 let mut visited: HashSet<String> = HashSet::new();
205 let mut on_stack: HashSet<String> = HashSet::new();
206 let mut stack: Vec<String> = Vec::new();
207 for name in struct_defs.keys() {
208 if !visited.contains(name) {
209 if let Some(cycle) = dfs(name, &graph, &mut visited, &mut on_stack, &mut stack) {
210 let contains_weak = cycle
211 .iter()
212 .any(|node| struct_has_weak.get(node).copied().unwrap_or(false));
213 if contains_weak {
214 continue;
215 }
216
217 let description = cycle.join(" -> ");
218 return Err(self.type_error(format!(
219 "Strong ownership cycle detected: {}. Mark at least one field as 'ref' to break the cycle.",
220 description
221 )));
222 }
223 }
224 }
225
226 Ok(())
227 }
228
229 fn collect_strong_struct_targets(
230 &self,
231 ty: &Type,
232 parent_module: Option<&str>,
233 struct_defs: &HashMap<String, StructDef>,
234 simple_to_full: &HashMap<String, Vec<String>>,
235 out: &mut HashSet<String>,
236 ) {
237 match &ty.kind {
238 TypeKind::Named(name) => {
239 if let Some(resolved) = self.resolve_struct_name_for_cycle(
240 name,
241 parent_module,
242 struct_defs,
243 simple_to_full,
244 ) {
245 out.insert(resolved);
246 }
247 }
248
249 TypeKind::Array(inner)
250 | TypeKind::Ref(inner)
251 | TypeKind::MutRef(inner)
252 | TypeKind::Option(inner) => {
253 self.collect_strong_struct_targets(
254 inner,
255 parent_module,
256 struct_defs,
257 simple_to_full,
258 out,
259 );
260 }
261
262 TypeKind::Map(key, value) => {
263 self.collect_strong_struct_targets(
264 key,
265 parent_module,
266 struct_defs,
267 simple_to_full,
268 out,
269 );
270 self.collect_strong_struct_targets(
271 value,
272 parent_module,
273 struct_defs,
274 simple_to_full,
275 out,
276 );
277 }
278
279 TypeKind::Tuple(elements) | TypeKind::Union(elements) => {
280 for element in elements {
281 self.collect_strong_struct_targets(
282 element,
283 parent_module,
284 struct_defs,
285 simple_to_full,
286 out,
287 );
288 }
289 }
290
291 TypeKind::Result(ok, err) => {
292 self.collect_strong_struct_targets(
293 ok,
294 parent_module,
295 struct_defs,
296 simple_to_full,
297 out,
298 );
299 self.collect_strong_struct_targets(
300 err,
301 parent_module,
302 struct_defs,
303 simple_to_full,
304 out,
305 );
306 }
307
308 TypeKind::GenericInstance { type_args, .. } => {
309 for arg in type_args {
310 self.collect_strong_struct_targets(
311 arg,
312 parent_module,
313 struct_defs,
314 simple_to_full,
315 out,
316 );
317 }
318 }
319
320 _ => {}
321 }
322 }
323
324 fn resolve_struct_name_for_cycle(
325 &self,
326 name: &str,
327 parent_module: Option<&str>,
328 struct_defs: &HashMap<String, StructDef>,
329 simple_to_full: &HashMap<String, Vec<String>>,
330 ) -> Option<String> {
331 if struct_defs.contains_key(name) {
332 return Some(name.to_string());
333 }
334
335 if name.contains('.') {
336 return None;
337 }
338
339 if let Some(candidates) = simple_to_full.get(name) {
340 if candidates.len() == 1 {
341 return Some(candidates[0].clone());
342 }
343
344 if let Some(module) = parent_module {
345 for candidate in candidates {
346 if let Some((candidate_module, _)) = candidate.rsplit_once('.') {
347 if candidate_module == module {
348 return Some(candidate.clone());
349 }
350 }
351 }
352 }
353 }
354
355 None
356 }
357
358 pub fn set_imports_by_module(&mut self, map: HashMap<String, ModuleImports>) {
359 self.imports_by_module = map;
360 }
361
362 pub fn take_type_info(&mut self) -> TypeCollection {
363 TypeCollection {
364 expr_types: mem::take(&mut self.expr_types_by_module),
365 variable_types: mem::take(&mut self.variable_types_by_module),
366 }
367 }
368
369 pub fn function_signatures(&self) -> HashMap<String, type_env::FunctionSignature> {
370 self.env.function_signatures()
371 }
372
373 pub fn struct_definitions(&self) -> HashMap<String, StructDef> {
374 self.env.struct_definitions()
375 }
376
377 pub fn enum_definitions(&self) -> HashMap<String, EnumDef> {
378 self.env.enum_definitions()
379 }
380
381 fn register_module_init_locals(&mut self, items: &[Item]) -> Result<()> {
382 let module = match &self.current_module {
383 Some(m) => m.clone(),
384 None => return Ok(()),
385 };
386 let init_name = format!("__init@{}", module);
387 for item in items {
388 if let ItemKind::Function(func) = &item.kind {
389 if func.name == init_name {
390 for stmt in &func.body {
391 if let StmtKind::Local {
392 bindings,
393 ref mutable,
394 initializer,
395 } = &stmt.kind
396 {
397 self.check_local_stmt(
398 bindings.as_slice(),
399 *mutable,
400 initializer.as_ref().map(|values| values.as_slice()),
401 )?;
402 }
403 }
404 }
405 }
406 }
407
408 Ok(())
409 }
410
411 pub fn resolve_function_key(&self, name: &str) -> String {
412 if name.contains('.') || name.contains(':') {
413 return name.to_string();
414 }
415
416 if let Some(module) = &self.current_module {
417 if let Some(imports) = self.imports_by_module.get(module) {
418 if let Some(fq) = imports.function_aliases.get(name) {
419 return fq.clone();
420 }
421 }
422
423 let qualified = format!("{}.{}", module, name);
424 if self.env.lookup_function(&qualified).is_some() {
425 return qualified;
426 }
427
428 if self.env.lookup_function(name).is_some() {
429 return name.to_string();
430 }
431
432 return qualified;
433 }
434
435 name.to_string()
436 }
437
438 pub fn resolve_module_alias(&self, alias: &str) -> Option<String> {
439 if let Some(module) = &self.current_module {
440 if let Some(imports) = self.imports_by_module.get(module) {
441 if let Some(m) = imports.module_aliases.get(alias) {
442 return Some(m.clone());
443 }
444 }
445 }
446
447 None
448 }
449
450 pub fn resolve_type_key(&self, name: &str) -> String {
451 if let Some((head, tail)) = name.split_once('.') {
452 if let Some(module) = &self.current_module {
453 if let Some(imports) = self.imports_by_module.get(module) {
454 if let Some(real_module) = imports.module_aliases.get(head) {
455 if tail.is_empty() {
456 return real_module.clone();
457 } else {
458 return format!("{}.{}", real_module, tail);
459 }
460 }
461 }
462 }
463
464 return name.to_string();
465 }
466
467 if self.env.lookup_struct(name).is_some()
468 || self.env.lookup_enum(name).is_some()
469 || self.env.lookup_trait(name).is_some()
470 {
471 return name.to_string();
472 }
473
474 if self.env.is_builtin_type(name) {
475 return name.to_string();
476 }
477
478 if let Some(module) = &self.current_module {
479 if let Some(imports) = self.imports_by_module.get(module) {
480 if let Some(fq) = imports.type_aliases.get(name) {
481 return fq.clone();
482 }
483 }
484
485 return format!("{}.{}", module, name);
486 }
487
488 name.to_string()
489 }
490
491 fn register_type_definition(&mut self, item: &Item) -> Result<()> {
492 match &item.kind {
493 ItemKind::Struct(s) => {
494 let mut s2 = s.clone();
495 if let Some(module) = &self.current_module {
496 if !s2.name.contains('.') {
497 s2.name = format!("{}.{}", module, s2.name);
498 }
499 }
500
501 self.env.register_struct(&s2)?;
502 }
503
504 ItemKind::Enum(e) => {
505 let mut e2 = e.clone();
506 if let Some(module) = &self.current_module {
507 if !e2.name.contains('.') {
508 e2.name = format!("{}.{}", module, e2.name);
509 }
510 }
511
512 self.env.register_enum(&e2)?;
513 }
514
515 ItemKind::Trait(t) => {
516 let mut t2 = t.clone();
517 if let Some(module) = &self.current_module {
518 if !t2.name.contains('.') {
519 t2.name = format!("{}.{}", module, t2.name);
520 }
521 }
522
523 self.env.register_trait(&t2)?;
524 }
525
526 ItemKind::TypeAlias {
527 name,
528 type_params,
529 target,
530 } => {
531 let qname = if let Some(module) = &self.current_module {
532 if name.contains('.') {
533 name.clone()
534 } else {
535 format!("{}.{}", module, name)
536 }
537 } else {
538 name.clone()
539 };
540 self.env
541 .register_type_alias(qname, type_params.clone(), target.clone())?;
542 }
543
544 _ => {}
545 }
546
547 Ok(())
548 }
549
550 fn type_error(&self, message: String) -> LustError {
551 LustError::TypeError { message }
552 }
553
554 fn type_error_at(&self, message: String, span: Span) -> LustError {
555 if span.start_line > 0 {
556 LustError::TypeErrorWithSpan {
557 message,
558 line: span.start_line,
559 column: span.start_col,
560 module: self.current_module.clone(),
561 }
562 } else {
563 LustError::TypeError { message }
564 }
565 }
566
567 fn types_equal(&self, t1: &Type, t2: &Type) -> bool {
568 t1.kind == t2.kind
569 }
570
571 pub fn canonicalize_type(&self, ty: &Type) -> Type {
572 use crate::ast::TypeKind as TK;
573 match &ty.kind {
574 TK::Named(name) => Type::new(TK::Named(self.resolve_type_key(name)), ty.span),
575 TK::Array(inner) => {
576 Type::new(TK::Array(Box::new(self.canonicalize_type(inner))), ty.span)
577 }
578
579 TK::Tuple(elements) => Type::new(
580 TK::Tuple(elements.iter().map(|t| self.canonicalize_type(t)).collect()),
581 ty.span,
582 ),
583 TK::Option(inner) => {
584 Type::new(TK::Option(Box::new(self.canonicalize_type(inner))), ty.span)
585 }
586
587 TK::Result(ok, err) => Type::new(
588 TK::Result(
589 Box::new(self.canonicalize_type(ok)),
590 Box::new(self.canonicalize_type(err)),
591 ),
592 ty.span,
593 ),
594 TK::Map(k, v) => Type::new(
595 TK::Map(
596 Box::new(self.canonicalize_type(k)),
597 Box::new(self.canonicalize_type(v)),
598 ),
599 ty.span,
600 ),
601 TK::Ref(inner) => Type::new(TK::Ref(Box::new(self.canonicalize_type(inner))), ty.span),
602 TK::MutRef(inner) => {
603 Type::new(TK::MutRef(Box::new(self.canonicalize_type(inner))), ty.span)
604 }
605
606 TK::Pointer { mutable, pointee } => Type::new(
607 TK::Pointer {
608 mutable: *mutable,
609 pointee: Box::new(self.canonicalize_type(pointee)),
610 },
611 ty.span,
612 ),
613 _ => ty.clone(),
614 }
615 }
616
617 fn unify(&self, expected: &Type, actual: &Type) -> Result<()> {
618 let span = if actual.span.start_line > 0 {
619 Some(actual.span)
620 } else if expected.span.start_line > 0 {
621 Some(expected.span)
622 } else {
623 None
624 };
625 self.unify_at(expected, actual, span)
626 }
627
628 fn unify_at(&self, expected: &Type, actual: &Type, span: Option<Span>) -> Result<()> {
629 if matches!(expected.kind, TypeKind::Unknown) || matches!(actual.kind, TypeKind::Unknown) {
630 return Ok(());
631 }
632
633 if matches!(expected.kind, TypeKind::Infer) || matches!(actual.kind, TypeKind::Infer) {
634 return Ok(());
635 }
636
637 match (&expected.kind, &actual.kind) {
638 (TypeKind::Union(expected_types), TypeKind::Union(actual_types)) => {
639 if expected_types.len() != actual_types.len() {
640 return Err(self.type_error(format!(
641 "Union types have different number of members: expected {}, got {}",
642 expected_types.len(),
643 actual_types.len()
644 )));
645 }
646
647 for exp_type in expected_types {
648 let mut found = false;
649 for act_type in actual_types {
650 if self.types_equal(exp_type, act_type) {
651 found = true;
652 break;
653 }
654 }
655
656 if !found {
657 return Err(match span {
658 Some(s) => self.type_error_at(
659 format!(
660 "Union type member '{}' not found in actual union",
661 exp_type
662 ),
663 s,
664 ),
665 None => self.type_error(format!(
666 "Union type member '{}' not found in actual union",
667 exp_type
668 )),
669 });
670 }
671 }
672
673 return Ok(());
674 }
675
676 (TypeKind::Union(expected_types), _) => {
677 for union_member in expected_types {
678 if self.unify(union_member, actual).is_ok() {
679 return Ok(());
680 }
681 }
682
683 return Err(match span {
684 Some(s) => self.type_error_at(
685 format!("Type '{}' is not compatible with union type", actual),
686 s,
687 ),
688 None => self.type_error(format!(
689 "Type '{}' is not compatible with union type",
690 actual
691 )),
692 });
693 }
694
695 (_, TypeKind::Union(actual_types)) => {
696 for union_member in actual_types {
697 self.unify(expected, union_member)?;
698 }
699
700 return Ok(());
701 }
702
703 _ => {}
704 }
705
706 match (&expected.kind, &actual.kind) {
707 (TypeKind::Tuple(expected_elems), TypeKind::Tuple(actual_elems)) => {
708 if expected_elems.len() != actual_elems.len() {
709 return Err(match span {
710 Some(s) => self.type_error_at(
711 format!(
712 "Tuple length mismatch: expected {} element(s), got {}",
713 expected_elems.len(),
714 actual_elems.len()
715 ),
716 s,
717 ),
718 None => self.type_error(format!(
719 "Tuple length mismatch: expected {} element(s), got {}",
720 expected_elems.len(),
721 actual_elems.len()
722 )),
723 });
724 }
725
726 for (exp_elem, act_elem) in expected_elems.iter().zip(actual_elems.iter()) {
727 self.unify(exp_elem, act_elem)?;
728 }
729
730 return Ok(());
731 }
732
733 (TypeKind::Tuple(_), _) | (_, TypeKind::Tuple(_)) => {
734 return Err(match span {
735 Some(s) => self.type_error_at(
736 format!("Tuple type is not compatible with type '{}'", actual),
737 s,
738 ),
739 None => self.type_error(format!(
740 "Tuple type is not compatible with type '{}'",
741 actual
742 )),
743 })
744 }
745
746 (TypeKind::Named(name), TypeKind::Array(_))
747 | (TypeKind::Array(_), TypeKind::Named(name))
748 if name == "Array" =>
749 {
750 return Ok(());
751 }
752
753 (TypeKind::Array(exp_el), TypeKind::Array(act_el)) => {
754 if matches!(exp_el.kind, TypeKind::Unknown | TypeKind::Infer)
755 || matches!(act_el.kind, TypeKind::Unknown | TypeKind::Infer)
756 {
757 return Ok(());
758 } else {
759 return self.unify(exp_el, act_el);
760 }
761 }
762
763 (TypeKind::Named(name), TypeKind::Option(_))
764 | (TypeKind::Option(_), TypeKind::Named(name))
765 if name == "Option" =>
766 {
767 return Ok(());
768 }
769
770 (TypeKind::Option(exp_inner), TypeKind::Option(act_inner)) => {
771 if matches!(exp_inner.kind, TypeKind::Unknown | TypeKind::Infer)
772 || matches!(act_inner.kind, TypeKind::Unknown | TypeKind::Infer)
773 {
774 return Ok(());
775 } else {
776 return self.unify(exp_inner, act_inner);
777 }
778 }
779
780 (TypeKind::Named(name), TypeKind::Result(_, _))
781 | (TypeKind::Result(_, _), TypeKind::Named(name))
782 if name == "Result" =>
783 {
784 return Ok(());
785 }
786
787 (TypeKind::Result(exp_ok, exp_err), TypeKind::Result(act_ok, act_err)) => {
788 if matches!(exp_ok.kind, TypeKind::Unknown | TypeKind::Infer)
789 || matches!(act_ok.kind, TypeKind::Unknown | TypeKind::Infer)
790 {
791 if matches!(exp_err.kind, TypeKind::Unknown | TypeKind::Infer)
792 || matches!(act_err.kind, TypeKind::Unknown | TypeKind::Infer)
793 {
794 return Ok(());
795 } else {
796 return self.unify(exp_err, act_err);
797 }
798 } else {
799 self.unify(exp_ok, act_ok)?;
800 return self.unify(exp_err, act_err);
801 }
802 }
803
804 _ => {}
805 }
806
807 match (&expected.kind, &actual.kind) {
808 (TypeKind::Table, TypeKind::Map(key, val)) => {
809 if matches!(key.kind, TypeKind::Unknown) && matches!(val.kind, TypeKind::Unknown) {
810 return Ok(());
811 }
812 }
813
814 (TypeKind::Map(key, val), TypeKind::Table) => {
815 if matches!(key.kind, TypeKind::Unknown) && matches!(val.kind, TypeKind::Unknown) {
816 return Ok(());
817 }
818 }
819
820 _ => {}
821 }
822
823 if self.types_equal(expected, actual) {
824 Ok(())
825 } else {
826 Err(match span {
827 Some(s) => self.type_error_at(
828 format!("Type mismatch: expected '{}', got '{}'", expected, actual),
829 s,
830 ),
831 None => self.type_error(format!(
832 "Type mismatch: expected '{}', got '{}'",
833 expected, actual
834 )),
835 })
836 }
837 }
838
839 fn types_compatible(&self, expected: &Type, actual: &Type) -> bool {
840 if matches!(expected.kind, TypeKind::Unknown) || matches!(actual.kind, TypeKind::Unknown) {
841 return true;
842 }
843
844 if matches!(expected.kind, TypeKind::Infer) || matches!(actual.kind, TypeKind::Infer) {
845 return true;
846 }
847
848 match (&expected.kind, &actual.kind) {
849 (TypeKind::Generic(_), TypeKind::Generic(_)) => return true,
850 (TypeKind::Generic(_), _) | (_, TypeKind::Generic(_)) => return true,
851 _ => {}
852 }
853
854 match (&expected.kind, &actual.kind) {
855 (TypeKind::Array(e1), TypeKind::Array(e2)) => {
856 return self.types_compatible(e1, e2);
857 }
858
859 (TypeKind::Named(name), TypeKind::Array(_))
860 | (TypeKind::Array(_), TypeKind::Named(name))
861 if name == "Array" =>
862 {
863 return true;
864 }
865
866 _ => {}
867 }
868
869 match (&expected.kind, &actual.kind) {
870 (TypeKind::Map(k1, v1), TypeKind::Map(k2, v2)) => {
871 return self.types_compatible(k1, k2) && self.types_compatible(v1, v2);
872 }
873
874 _ => {}
875 }
876
877 match (&expected.kind, &actual.kind) {
878 (TypeKind::Option(t1), TypeKind::Option(t2)) => {
879 return self.types_compatible(t1, t2);
880 }
881
882 (TypeKind::Named(name), TypeKind::Option(_))
883 | (TypeKind::Option(_), TypeKind::Named(name))
884 if name == "Option" =>
885 {
886 return true;
887 }
888
889 _ => {}
890 }
891
892 match (&expected.kind, &actual.kind) {
893 (TypeKind::Result(ok1, err1), TypeKind::Result(ok2, err2)) => {
894 return self.types_compatible(ok1, ok2) && self.types_compatible(err1, err2);
895 }
896
897 (TypeKind::Named(name), TypeKind::Result(_, _))
898 | (TypeKind::Result(_, _), TypeKind::Named(name))
899 if name == "Result" =>
900 {
901 return true;
902 }
903
904 _ => {}
905 }
906
907 match (&expected.kind, &actual.kind) {
908 (
909 TypeKind::Function {
910 params: p1,
911 return_type: r1,
912 },
913 TypeKind::Function {
914 params: p2,
915 return_type: r2,
916 },
917 ) => {
918 if p1.len() != p2.len() {
919 return false;
920 }
921
922 for (t1, t2) in p1.iter().zip(p2.iter()) {
923 if !self.types_compatible(t1, t2) {
924 return false;
925 }
926 }
927
928 return self.types_compatible(r1, r2);
929 }
930
931 _ => {}
932 }
933
934 self.types_equal(expected, actual)
935 }
936
937 fn unify_with_bounds(&self, expected: &Type, actual: &Type) -> Result<()> {
938 if let TypeKind::Generic(type_param) = &expected.kind {
939 if let Some(trait_names) = self.current_trait_bounds.get(type_param) {
940 for trait_name in trait_names {
941 if !self.env.type_implements_trait(actual, trait_name) {
942 return Err(self.type_error(format!(
943 "Type '{}' does not implement required trait '{}'",
944 actual, trait_name
945 )));
946 }
947 }
948
949 return Ok(());
950 }
951
952 return Ok(());
953 }
954
955 self.unify(expected, actual)
956 }
957}