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(
370 &self,
371 ) -> HashMap<String, type_env::FunctionSignature> {
372 self.env.function_signatures()
373 }
374
375 pub fn struct_definitions(&self) -> HashMap<String, StructDef> {
376 self.env.struct_definitions()
377 }
378
379 pub fn enum_definitions(&self) -> HashMap<String, EnumDef> {
380 self.env.enum_definitions()
381 }
382
383 fn register_module_init_locals(&mut self, items: &[Item]) -> Result<()> {
384 let module = match &self.current_module {
385 Some(m) => m.clone(),
386 None => return Ok(()),
387 };
388 let init_name = format!("__init@{}", module);
389 for item in items {
390 if let ItemKind::Function(func) = &item.kind {
391 if func.name == init_name {
392 for stmt in &func.body {
393 if let StmtKind::Local {
394 bindings,
395 ref mutable,
396 initializer,
397 } = &stmt.kind
398 {
399 self.check_local_stmt(
400 bindings.as_slice(),
401 *mutable,
402 initializer.as_ref().map(|values| values.as_slice()),
403 )?;
404 }
405 }
406 }
407 }
408 }
409
410 Ok(())
411 }
412
413 pub fn resolve_function_key(&self, name: &str) -> String {
414 if name.contains('.') || name.contains(':') {
415 return name.to_string();
416 }
417
418 if let Some(module) = &self.current_module {
419 if let Some(imports) = self.imports_by_module.get(module) {
420 if let Some(fq) = imports.function_aliases.get(name) {
421 return fq.clone();
422 }
423 }
424
425 let qualified = format!("{}.{}", module, name);
426 if self.env.lookup_function(&qualified).is_some() {
427 return qualified;
428 }
429
430 if self.env.lookup_function(name).is_some() {
431 return name.to_string();
432 }
433
434 return qualified;
435 }
436
437 name.to_string()
438 }
439
440 pub fn resolve_module_alias(&self, alias: &str) -> Option<String> {
441 if let Some(module) = &self.current_module {
442 if let Some(imports) = self.imports_by_module.get(module) {
443 if let Some(m) = imports.module_aliases.get(alias) {
444 return Some(m.clone());
445 }
446 }
447 }
448
449 None
450 }
451
452 pub fn resolve_type_key(&self, name: &str) -> String {
453 if let Some((head, tail)) = name.split_once('.') {
454 if let Some(module) = &self.current_module {
455 if let Some(imports) = self.imports_by_module.get(module) {
456 if let Some(real_module) = imports.module_aliases.get(head) {
457 if tail.is_empty() {
458 return real_module.clone();
459 } else {
460 return format!("{}.{}", real_module, tail);
461 }
462 }
463 }
464 }
465
466 return name.to_string();
467 }
468
469 if self.env.lookup_struct(name).is_some()
470 || self.env.lookup_enum(name).is_some()
471 || self.env.lookup_trait(name).is_some()
472 {
473 return name.to_string();
474 }
475
476 if self.env.is_builtin_type(name) {
477 return name.to_string();
478 }
479
480 if let Some(module) = &self.current_module {
481 if let Some(imports) = self.imports_by_module.get(module) {
482 if let Some(fq) = imports.type_aliases.get(name) {
483 return fq.clone();
484 }
485 }
486
487 return format!("{}.{}", module, name);
488 }
489
490 name.to_string()
491 }
492
493 fn register_type_definition(&mut self, item: &Item) -> Result<()> {
494 match &item.kind {
495 ItemKind::Struct(s) => {
496 let mut s2 = s.clone();
497 if let Some(module) = &self.current_module {
498 if !s2.name.contains('.') {
499 s2.name = format!("{}.{}", module, s2.name);
500 }
501 }
502
503 self.env.register_struct(&s2)?;
504 }
505
506 ItemKind::Enum(e) => {
507 let mut e2 = e.clone();
508 if let Some(module) = &self.current_module {
509 if !e2.name.contains('.') {
510 e2.name = format!("{}.{}", module, e2.name);
511 }
512 }
513
514 self.env.register_enum(&e2)?;
515 }
516
517 ItemKind::Trait(t) => {
518 let mut t2 = t.clone();
519 if let Some(module) = &self.current_module {
520 if !t2.name.contains('.') {
521 t2.name = format!("{}.{}", module, t2.name);
522 }
523 }
524
525 self.env.register_trait(&t2)?;
526 }
527
528 ItemKind::TypeAlias {
529 name,
530 type_params,
531 target,
532 } => {
533 let qname = if let Some(module) = &self.current_module {
534 if name.contains('.') {
535 name.clone()
536 } else {
537 format!("{}.{}", module, name)
538 }
539 } else {
540 name.clone()
541 };
542 self.env
543 .register_type_alias(qname, type_params.clone(), target.clone())?;
544 }
545
546 _ => {}
547 }
548
549 Ok(())
550 }
551
552 fn type_error(&self, message: String) -> LustError {
553 LustError::TypeError { message }
554 }
555
556 fn type_error_at(&self, message: String, span: Span) -> LustError {
557 if span.start_line > 0 {
558 LustError::TypeErrorWithSpan {
559 message,
560 line: span.start_line,
561 column: span.start_col,
562 module: self.current_module.clone(),
563 }
564 } else {
565 LustError::TypeError { message }
566 }
567 }
568
569 fn types_equal(&self, t1: &Type, t2: &Type) -> bool {
570 t1.kind == t2.kind
571 }
572
573 pub fn canonicalize_type(&self, ty: &Type) -> Type {
574 use crate::ast::TypeKind as TK;
575 match &ty.kind {
576 TK::Named(name) => Type::new(TK::Named(self.resolve_type_key(name)), ty.span),
577 TK::Array(inner) => {
578 Type::new(TK::Array(Box::new(self.canonicalize_type(inner))), ty.span)
579 }
580
581 TK::Tuple(elements) => Type::new(
582 TK::Tuple(elements.iter().map(|t| self.canonicalize_type(t)).collect()),
583 ty.span,
584 ),
585 TK::Option(inner) => {
586 Type::new(TK::Option(Box::new(self.canonicalize_type(inner))), ty.span)
587 }
588
589 TK::Result(ok, err) => Type::new(
590 TK::Result(
591 Box::new(self.canonicalize_type(ok)),
592 Box::new(self.canonicalize_type(err)),
593 ),
594 ty.span,
595 ),
596 TK::Map(k, v) => Type::new(
597 TK::Map(
598 Box::new(self.canonicalize_type(k)),
599 Box::new(self.canonicalize_type(v)),
600 ),
601 ty.span,
602 ),
603 TK::Ref(inner) => Type::new(TK::Ref(Box::new(self.canonicalize_type(inner))), ty.span),
604 TK::MutRef(inner) => {
605 Type::new(TK::MutRef(Box::new(self.canonicalize_type(inner))), ty.span)
606 }
607
608 TK::Pointer { mutable, pointee } => Type::new(
609 TK::Pointer {
610 mutable: *mutable,
611 pointee: Box::new(self.canonicalize_type(pointee)),
612 },
613 ty.span,
614 ),
615 _ => ty.clone(),
616 }
617 }
618
619 fn unify(&self, expected: &Type, actual: &Type) -> Result<()> {
620 let span = if actual.span.start_line > 0 {
621 Some(actual.span)
622 } else if expected.span.start_line > 0 {
623 Some(expected.span)
624 } else {
625 None
626 };
627 self.unify_at(expected, actual, span)
628 }
629
630 fn unify_at(&self, expected: &Type, actual: &Type, span: Option<Span>) -> Result<()> {
631 if matches!(expected.kind, TypeKind::Unknown) || matches!(actual.kind, TypeKind::Unknown) {
632 return Ok(());
633 }
634
635 if matches!(expected.kind, TypeKind::Infer) || matches!(actual.kind, TypeKind::Infer) {
636 return Ok(());
637 }
638
639 match (&expected.kind, &actual.kind) {
640 (TypeKind::Union(expected_types), TypeKind::Union(actual_types)) => {
641 if expected_types.len() != actual_types.len() {
642 return Err(self.type_error(format!(
643 "Union types have different number of members: expected {}, got {}",
644 expected_types.len(),
645 actual_types.len()
646 )));
647 }
648
649 for exp_type in expected_types {
650 let mut found = false;
651 for act_type in actual_types {
652 if self.types_equal(exp_type, act_type) {
653 found = true;
654 break;
655 }
656 }
657
658 if !found {
659 return Err(match span {
660 Some(s) => self.type_error_at(
661 format!(
662 "Union type member '{}' not found in actual union",
663 exp_type
664 ),
665 s,
666 ),
667 None => self.type_error(format!(
668 "Union type member '{}' not found in actual union",
669 exp_type
670 )),
671 });
672 }
673 }
674
675 return Ok(());
676 }
677
678 (TypeKind::Union(expected_types), _) => {
679 for union_member in expected_types {
680 if self.unify(union_member, actual).is_ok() {
681 return Ok(());
682 }
683 }
684
685 return Err(match span {
686 Some(s) => self.type_error_at(
687 format!("Type '{}' is not compatible with union type", actual),
688 s,
689 ),
690 None => self.type_error(format!(
691 "Type '{}' is not compatible with union type",
692 actual
693 )),
694 });
695 }
696
697 (_, TypeKind::Union(actual_types)) => {
698 for union_member in actual_types {
699 self.unify(expected, union_member)?;
700 }
701
702 return Ok(());
703 }
704
705 _ => {}
706 }
707
708 match (&expected.kind, &actual.kind) {
709 (TypeKind::Tuple(expected_elems), TypeKind::Tuple(actual_elems)) => {
710 if expected_elems.len() != actual_elems.len() {
711 return Err(match span {
712 Some(s) => self.type_error_at(
713 format!(
714 "Tuple length mismatch: expected {} element(s), got {}",
715 expected_elems.len(),
716 actual_elems.len()
717 ),
718 s,
719 ),
720 None => self.type_error(format!(
721 "Tuple length mismatch: expected {} element(s), got {}",
722 expected_elems.len(),
723 actual_elems.len()
724 )),
725 });
726 }
727
728 for (exp_elem, act_elem) in expected_elems.iter().zip(actual_elems.iter()) {
729 self.unify(exp_elem, act_elem)?;
730 }
731
732 return Ok(());
733 }
734
735 (TypeKind::Tuple(_), _) | (_, TypeKind::Tuple(_)) => {
736 return Err(match span {
737 Some(s) => self.type_error_at(
738 format!("Tuple type is not compatible with type '{}'", actual),
739 s,
740 ),
741 None => self.type_error(format!(
742 "Tuple type is not compatible with type '{}'",
743 actual
744 )),
745 })
746 }
747
748 (TypeKind::Named(name), TypeKind::Array(_))
749 | (TypeKind::Array(_), TypeKind::Named(name))
750 if name == "Array" =>
751 {
752 return Ok(());
753 }
754
755 (TypeKind::Array(exp_el), TypeKind::Array(act_el)) => {
756 if matches!(exp_el.kind, TypeKind::Unknown | TypeKind::Infer)
757 || matches!(act_el.kind, TypeKind::Unknown | TypeKind::Infer)
758 {
759 return Ok(());
760 } else {
761 return self.unify(exp_el, act_el);
762 }
763 }
764
765 (TypeKind::Named(name), TypeKind::Option(_))
766 | (TypeKind::Option(_), TypeKind::Named(name))
767 if name == "Option" =>
768 {
769 return Ok(());
770 }
771
772 (TypeKind::Option(exp_inner), TypeKind::Option(act_inner)) => {
773 if matches!(exp_inner.kind, TypeKind::Unknown | TypeKind::Infer)
774 || matches!(act_inner.kind, TypeKind::Unknown | TypeKind::Infer)
775 {
776 return Ok(());
777 } else {
778 return self.unify(exp_inner, act_inner);
779 }
780 }
781
782 (TypeKind::Named(name), TypeKind::Result(_, _))
783 | (TypeKind::Result(_, _), TypeKind::Named(name))
784 if name == "Result" =>
785 {
786 return Ok(());
787 }
788
789 (TypeKind::Result(exp_ok, exp_err), TypeKind::Result(act_ok, act_err)) => {
790 if matches!(exp_ok.kind, TypeKind::Unknown | TypeKind::Infer)
791 || matches!(act_ok.kind, TypeKind::Unknown | TypeKind::Infer)
792 {
793 if matches!(exp_err.kind, TypeKind::Unknown | TypeKind::Infer)
794 || matches!(act_err.kind, TypeKind::Unknown | TypeKind::Infer)
795 {
796 return Ok(());
797 } else {
798 return self.unify(exp_err, act_err);
799 }
800 } else {
801 self.unify(exp_ok, act_ok)?;
802 return self.unify(exp_err, act_err);
803 }
804 }
805
806 _ => {}
807 }
808
809 match (&expected.kind, &actual.kind) {
810 (TypeKind::Table, TypeKind::Map(key, val)) => {
811 if matches!(key.kind, TypeKind::Unknown) && matches!(val.kind, TypeKind::Unknown) {
812 return Ok(());
813 }
814 }
815
816 (TypeKind::Map(key, val), TypeKind::Table) => {
817 if matches!(key.kind, TypeKind::Unknown) && matches!(val.kind, TypeKind::Unknown) {
818 return Ok(());
819 }
820 }
821
822 _ => {}
823 }
824
825 if self.types_equal(expected, actual) {
826 Ok(())
827 } else {
828 Err(match span {
829 Some(s) => self.type_error_at(
830 format!("Type mismatch: expected '{}', got '{}'", expected, actual),
831 s,
832 ),
833 None => self.type_error(format!(
834 "Type mismatch: expected '{}', got '{}'",
835 expected, actual
836 )),
837 })
838 }
839 }
840
841 fn types_compatible(&self, expected: &Type, actual: &Type) -> bool {
842 if matches!(expected.kind, TypeKind::Unknown) || matches!(actual.kind, TypeKind::Unknown) {
843 return true;
844 }
845
846 if matches!(expected.kind, TypeKind::Infer) || matches!(actual.kind, TypeKind::Infer) {
847 return true;
848 }
849
850 match (&expected.kind, &actual.kind) {
851 (TypeKind::Generic(_), TypeKind::Generic(_)) => return true,
852 (TypeKind::Generic(_), _) | (_, TypeKind::Generic(_)) => return true,
853 _ => {}
854 }
855
856 match (&expected.kind, &actual.kind) {
857 (TypeKind::Array(e1), TypeKind::Array(e2)) => {
858 return self.types_compatible(e1, e2);
859 }
860
861 (TypeKind::Named(name), TypeKind::Array(_))
862 | (TypeKind::Array(_), TypeKind::Named(name))
863 if name == "Array" =>
864 {
865 return true;
866 }
867
868 _ => {}
869 }
870
871 match (&expected.kind, &actual.kind) {
872 (TypeKind::Map(k1, v1), TypeKind::Map(k2, v2)) => {
873 return self.types_compatible(k1, k2) && self.types_compatible(v1, v2);
874 }
875
876 _ => {}
877 }
878
879 match (&expected.kind, &actual.kind) {
880 (TypeKind::Option(t1), TypeKind::Option(t2)) => {
881 return self.types_compatible(t1, t2);
882 }
883
884 (TypeKind::Named(name), TypeKind::Option(_))
885 | (TypeKind::Option(_), TypeKind::Named(name))
886 if name == "Option" =>
887 {
888 return true;
889 }
890
891 _ => {}
892 }
893
894 match (&expected.kind, &actual.kind) {
895 (TypeKind::Result(ok1, err1), TypeKind::Result(ok2, err2)) => {
896 return self.types_compatible(ok1, ok2) && self.types_compatible(err1, err2);
897 }
898
899 (TypeKind::Named(name), TypeKind::Result(_, _))
900 | (TypeKind::Result(_, _), TypeKind::Named(name))
901 if name == "Result" =>
902 {
903 return true;
904 }
905
906 _ => {}
907 }
908
909 match (&expected.kind, &actual.kind) {
910 (
911 TypeKind::Function {
912 params: p1,
913 return_type: r1,
914 },
915 TypeKind::Function {
916 params: p2,
917 return_type: r2,
918 },
919 ) => {
920 if p1.len() != p2.len() {
921 return false;
922 }
923
924 for (t1, t2) in p1.iter().zip(p2.iter()) {
925 if !self.types_compatible(t1, t2) {
926 return false;
927 }
928 }
929
930 return self.types_compatible(r1, r2);
931 }
932
933 _ => {}
934 }
935
936 self.types_equal(expected, actual)
937 }
938
939 fn unify_with_bounds(&self, expected: &Type, actual: &Type) -> Result<()> {
940 if let TypeKind::Generic(type_param) = &expected.kind {
941 if let Some(trait_names) = self.current_trait_bounds.get(type_param) {
942 for trait_name in trait_names {
943 if !self.env.type_implements_trait(actual, trait_name) {
944 return Err(self.type_error(format!(
945 "Type '{}' does not implement required trait '{}'",
946 actual, trait_name
947 )));
948 }
949 }
950
951 return Ok(());
952 }
953
954 return Ok(());
955 }
956
957 self.unify(expected, actual)
958 }
959}