1use std::collections::{HashMap, HashSet};
34use std::fmt;
35use std::rc::Rc;
36use std::sync::Arc;
37
38#[derive(Debug, Clone, PartialEq, Eq, Hash)]
43pub struct TypeVar {
44 pub id: usize,
46 pub name: String,
48}
49
50impl TypeVar {
51 pub fn new(id: usize, name: impl Into<String>) -> Self {
53 TypeVar {
54 id,
55 name: name.into(),
56 }
57 }
58
59 pub fn fresh(id: usize) -> Self {
61 TypeVar {
62 id,
63 name: format!("t{}", id),
64 }
65 }
66}
67
68impl fmt::Display for TypeVar {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "'{}", self.name)
71 }
72}
73
74#[derive(Debug, Clone, PartialEq)]
83pub enum Type {
84 Var(TypeVar),
86
87 Int,
89
90 Bool,
92
93 String,
95
96 Unit,
98
99 Float,
101
102 Tuple(Vec<Type>),
104
105 List(Box<Type>),
107
108 Array(Box<Type>),
110
111 Function(Box<Type>, Box<Type>),
113
114 Record(HashMap<String, Type>),
116
117 Variant(String, Vec<Type>),
119}
120
121impl Type {
122 pub fn free_vars(&self) -> HashSet<TypeVar> {
127 match self {
128 Type::Var(v) => {
129 let mut set = HashSet::new();
130 set.insert(v.clone());
131 set
132 }
133 Type::Int | Type::Bool | Type::String | Type::Unit | Type::Float => HashSet::new(),
134 Type::Tuple(types) => types.iter().flat_map(|t| t.free_vars()).collect(),
135 Type::List(t) | Type::Array(t) => t.free_vars(),
136 Type::Function(arg, ret) => {
137 let mut set = arg.free_vars();
138 set.extend(ret.free_vars());
139 set
140 }
141 Type::Record(fields) => fields.values().flat_map(|t| t.free_vars()).collect(),
142 Type::Variant(_, params) => params.iter().flat_map(|t| t.free_vars()).collect(),
143 }
144 }
145
146 pub fn apply(&self, subst: &Substitution) -> Type {
150 match self {
151 Type::Var(v) => subst.lookup(v).unwrap_or_else(|| self.clone()),
152 Type::Int | Type::Bool | Type::String | Type::Unit | Type::Float => self.clone(),
153 Type::Tuple(types) => Type::Tuple(types.iter().map(|t| t.apply(subst)).collect()),
154 Type::List(t) => Type::List(Box::new(t.apply(subst))),
155 Type::Array(t) => Type::Array(Box::new(t.apply(subst))),
156 Type::Function(arg, ret) => {
157 Type::Function(Box::new(arg.apply(subst)), Box::new(ret.apply(subst)))
158 }
159 Type::Record(fields) => Type::Record(
160 fields
161 .iter()
162 .map(|(name, ty)| (name.clone(), ty.apply(subst)))
163 .collect(),
164 ),
165 Type::Variant(name, params) => Type::Variant(
166 name.clone(),
167 params.iter().map(|t| t.apply(subst)).collect(),
168 ),
169 }
170 }
171
172 pub fn occurs_check(&self, var: &TypeVar) -> bool {
177 match self {
178 Type::Var(v) => v == var,
179 Type::Int | Type::Bool | Type::String | Type::Unit | Type::Float => false,
180 Type::Tuple(types) => types.iter().any(|t| t.occurs_check(var)),
181 Type::List(t) | Type::Array(t) => t.occurs_check(var),
182 Type::Function(arg, ret) => arg.occurs_check(var) || ret.occurs_check(var),
183 Type::Record(fields) => fields.values().any(|t| t.occurs_check(var)),
184 Type::Variant(_, params) => params.iter().any(|t| t.occurs_check(var)),
185 }
186 }
187
188 pub fn function_multi(args: &[Type], ret: Type) -> Type {
193 args.iter().rev().fold(ret, |acc, arg| {
194 Type::Function(Box::new(arg.clone()), Box::new(acc))
195 })
196 }
197}
198
199impl fmt::Display for Type {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 match self {
202 Type::Var(v) => write!(f, "{}", v),
203 Type::Int => write!(f, "int"),
204 Type::Bool => write!(f, "bool"),
205 Type::String => write!(f, "string"),
206 Type::Unit => write!(f, "unit"),
207 Type::Float => write!(f, "float"),
208 Type::Tuple(types) => {
209 write!(f, "(")?;
210 for (i, ty) in types.iter().enumerate() {
211 if i > 0 {
212 write!(f, " * ")?;
213 }
214 write!(f, "{}", ty)?;
215 }
216 write!(f, ")")
217 }
218 Type::List(t) => write!(f, "{} list", t),
219 Type::Array(t) => write!(f, "{}[]", t),
220 Type::Function(arg, ret) => {
221 match **arg {
223 Type::Function(_, _) => write!(f, "({}) -> {}", arg, ret),
224 _ => write!(f, "{} -> {}", arg, ret),
225 }
226 }
227 Type::Record(fields) => {
228 write!(f, "{{")?;
229 let mut first = true;
230 for (name, ty) in fields {
231 if !first {
232 write!(f, "; ")?;
233 }
234 write!(f, "{}: {}", name, ty)?;
235 first = false;
236 }
237 write!(f, "}}")
238 }
239 Type::Variant(name, params) if params.is_empty() => write!(f, "{}", name),
240 Type::Variant(name, params) => {
241 write!(f, "{}<", name)?;
242 for (i, param) in params.iter().enumerate() {
243 if i > 0 {
244 write!(f, ", ")?;
245 }
246 write!(f, "{}", param)?;
247 }
248 write!(f, ">")
249 }
250 }
251 }
252}
253
254#[derive(Debug, Clone, PartialEq)]
259pub struct Substitution {
260 mappings: HashMap<TypeVar, Type>,
262}
263
264impl Substitution {
265 pub fn empty() -> Self {
267 Substitution {
268 mappings: HashMap::new(),
269 }
270 }
271
272 pub fn singleton(var: TypeVar, ty: Type) -> Self {
274 let mut mappings = HashMap::new();
275 mappings.insert(var, ty);
276 Substitution { mappings }
277 }
278
279 pub fn lookup(&self, var: &TypeVar) -> Option<Type> {
283 self.mappings.get(var).cloned()
284 }
285
286 pub fn insert(&mut self, var: TypeVar, ty: Type) {
288 self.mappings.insert(var, ty);
289 }
290
291 pub fn compose(s1: &Self, s2: &Self) -> Self {
296 let mut mappings = HashMap::new();
297
298 for (var, ty) in &s2.mappings {
300 mappings.insert(var.clone(), ty.apply(s1));
301 }
302
303 for (var, ty) in &s1.mappings {
305 if !mappings.contains_key(var) {
306 mappings.insert(var.clone(), ty.clone());
307 }
308 }
309
310 Substitution { mappings }
311 }
312
313 pub fn apply_type(&self, ty: &Type) -> Type {
315 ty.apply(self)
316 }
317
318 pub fn apply_scheme(&self, scheme: &TypeScheme) -> TypeScheme {
320 let mut subst = self.clone();
322 for var in &scheme.vars {
323 subst.mappings.remove(var);
324 }
325 TypeScheme {
326 vars: scheme.vars.clone(),
327 ty: scheme.ty.apply(&subst),
328 }
329 }
330
331 pub fn is_empty(&self) -> bool {
333 self.mappings.is_empty()
334 }
335
336 pub fn len(&self) -> usize {
338 self.mappings.len()
339 }
340
341 pub fn iter(&self) -> impl Iterator<Item = (&TypeVar, &Type)> {
343 self.mappings.iter()
344 }
345}
346
347impl fmt::Display for Substitution {
348 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
349 write!(f, "[")?;
350 let mut first = true;
351 for (var, ty) in &self.mappings {
352 if !first {
353 write!(f, ", ")?;
354 }
355 write!(f, "{} ↦ {}", var, ty)?;
356 first = false;
357 }
358 write!(f, "]")
359 }
360}
361
362#[derive(Debug, Clone, PartialEq)]
367pub struct TypeScheme {
368 pub vars: Vec<TypeVar>,
370 pub ty: Type,
372}
373
374impl TypeScheme {
375 pub fn mono(ty: Type) -> Self {
377 TypeScheme {
378 vars: Vec::new(),
379 ty,
380 }
381 }
382
383 pub fn poly(vars: Vec<TypeVar>, ty: Type) -> Self {
385 TypeScheme { vars, ty }
386 }
387
388 pub fn free_vars(&self) -> HashSet<TypeVar> {
392 let mut free = self.ty.free_vars();
393 for var in &self.vars {
394 free.remove(var);
395 }
396 free
397 }
398
399 pub fn apply(&self, subst: &Substitution) -> TypeScheme {
403 subst.apply_scheme(self)
404 }
405
406 pub fn is_mono(&self) -> bool {
408 self.vars.is_empty()
409 }
410
411 pub fn inner_type(&self) -> &Type {
413 &self.ty
414 }
415}
416
417impl fmt::Display for TypeScheme {
418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419 if self.vars.is_empty() {
420 write!(f, "{}", self.ty)
421 } else {
422 write!(f, "∀")?;
423 for (i, var) in self.vars.iter().enumerate() {
424 if i > 0 {
425 write!(f, " ")?;
426 }
427 write!(f, "{}", var)?;
428 }
429 write!(f, ". {}", self.ty)
430 }
431 }
432}
433
434#[derive(Debug, Clone, PartialEq)]
439pub struct TypeEnv {
440 bindings: HashMap<String, TypeScheme>,
442 parent: Option<Rc<TypeEnv>>,
444}
445
446impl TypeEnv {
447 pub fn new() -> Self {
449 TypeEnv {
450 bindings: HashMap::new(),
451 parent: None,
452 }
453 }
454
455 pub fn with_parent(parent: Rc<TypeEnv>) -> Self {
457 TypeEnv {
458 bindings: HashMap::new(),
459 parent: Some(parent),
460 }
461 }
462
463 pub fn extend(&self, name: String, scheme: TypeScheme) -> Self {
468 let mut bindings = HashMap::new();
469 bindings.insert(name, scheme);
470 TypeEnv {
471 bindings,
472 parent: Some(Rc::new(self.clone())),
473 }
474 }
475
476 pub fn insert(&mut self, name: String, scheme: TypeScheme) {
478 self.bindings.insert(name, scheme);
479 }
480
481 pub fn lookup(&self, name: &str) -> Option<&TypeScheme> {
485 self.bindings
486 .get(name)
487 .or_else(|| self.parent.as_ref().and_then(|parent| parent.lookup(name)))
488 }
489
490 pub fn free_vars(&self) -> HashSet<TypeVar> {
494 let mut free: HashSet<TypeVar> = self
495 .bindings
496 .values()
497 .flat_map(|scheme| scheme.free_vars())
498 .collect();
499
500 if let Some(parent) = &self.parent {
501 free.extend(parent.free_vars());
502 }
503
504 free
505 }
506
507 pub fn apply(&self, subst: &Substitution) -> TypeEnv {
509 TypeEnv {
510 bindings: self
511 .bindings
512 .iter()
513 .map(|(name, scheme)| (name.clone(), scheme.apply(subst)))
514 .collect(),
515 parent: self.parent.as_ref().map(|p| Rc::new(p.apply(subst))),
516 }
517 }
518
519 pub fn generalize(&self, ty: &Type) -> TypeScheme {
524 let env_vars = self.free_vars();
525 let type_vars = ty.free_vars();
526
527 let quantified: Vec<TypeVar> = type_vars
528 .into_iter()
529 .filter(|v| !env_vars.contains(v))
530 .collect();
531
532 TypeScheme::poly(quantified, ty.clone())
533 }
534
535 pub fn instantiate(
540 &self,
541 scheme: &TypeScheme,
542 fresh_var: &mut impl FnMut() -> TypeVar,
543 ) -> Type {
544 if scheme.vars.is_empty() {
545 return scheme.ty.clone();
546 }
547
548 let mut subst = Substitution::empty();
549 for var in &scheme.vars {
550 let fresh = fresh_var();
551 subst.insert(var.clone(), Type::Var(fresh));
552 }
553
554 scheme.ty.apply(&subst)
555 }
556
557 pub fn is_empty(&self) -> bool {
559 self.bindings.is_empty() && self.parent.is_none()
560 }
561
562 pub fn len(&self) -> usize {
564 self.bindings.len()
565 }
566
567 pub fn bindings(&self) -> impl Iterator<Item = (&String, &TypeScheme)> {
569 self.bindings.iter()
570 }
571}
572
573impl Default for TypeEnv {
574 fn default() -> Self {
575 Self::new()
576 }
577}
578
579impl fmt::Display for TypeEnv {
580 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
581 write!(f, "{{")?;
582 let mut first = true;
583 for (name, scheme) in &self.bindings {
584 if !first {
585 write!(f, ", ")?;
586 }
587 write!(f, "{}: {}", name, scheme)?;
588 first = false;
589 }
590 if let Some(parent) = &self.parent {
591 if !first {
592 write!(f, ", ")?;
593 }
594 write!(f, "parent: {}", parent)?;
595 }
596 write!(f, "}}")
597 }
598}
599
600#[cfg(test)]
601mod tests {
602 use super::*;
603
604 #[test]
609 fn test_typevar_new() {
610 let var = TypeVar::new(0, "a");
611 assert_eq!(var.id, 0);
612 assert_eq!(var.name, "a");
613 }
614
615 #[test]
616 fn test_typevar_fresh() {
617 let var = TypeVar::fresh(42);
618 assert_eq!(var.id, 42);
619 assert_eq!(var.name, "t42");
620 }
621
622 #[test]
623 fn test_typevar_display() {
624 let var = TypeVar::new(0, "a");
625 assert_eq!(format!("{}", var), "'a");
626 }
627
628 #[test]
629 fn test_typevar_equality() {
630 let var1 = TypeVar::new(0, "a");
631 let var2 = TypeVar::new(0, "a");
632 let var3 = TypeVar::new(1, "a");
633 assert_eq!(var1, var2);
634 assert_ne!(var1, var3);
635 }
636
637 #[test]
638 fn test_typevar_hash() {
639 let mut set = HashSet::new();
640 let var1 = TypeVar::new(0, "a");
641 let var2 = TypeVar::new(0, "a");
642 set.insert(var1.clone());
643 set.insert(var2);
644 assert_eq!(set.len(), 1);
645 }
646
647 #[test]
652 fn test_type_primitives() {
653 assert_eq!(format!("{}", Type::Int), "int");
654 assert_eq!(format!("{}", Type::Bool), "bool");
655 assert_eq!(format!("{}", Type::String), "string");
656 assert_eq!(format!("{}", Type::Unit), "unit");
657 assert_eq!(format!("{}", Type::Float), "float");
658 }
659
660 #[test]
661 fn test_type_var() {
662 let var = TypeVar::new(0, "a");
663 let ty = Type::Var(var);
664 assert_eq!(format!("{}", ty), "'a");
665 }
666
667 #[test]
668 fn test_type_function() {
669 let ty = Type::Function(Box::new(Type::Int), Box::new(Type::Bool));
670 assert_eq!(format!("{}", ty), "int -> bool");
671 }
672
673 #[test]
674 fn test_type_function_nested() {
675 let ty = Type::Function(
676 Box::new(Type::Function(Box::new(Type::Int), Box::new(Type::Bool))),
677 Box::new(Type::String),
678 );
679 assert_eq!(format!("{}", ty), "(int -> bool) -> string");
680 }
681
682 #[test]
683 fn test_type_tuple() {
684 let ty = Type::Tuple(vec![Type::Int, Type::Bool, Type::String]);
685 assert_eq!(format!("{}", ty), "(int * bool * string)");
686 }
687
688 #[test]
689 fn test_type_list() {
690 let ty = Type::List(Box::new(Type::Int));
691 assert_eq!(format!("{}", ty), "int list");
692 }
693
694 #[test]
695 fn test_type_array() {
696 let ty = Type::Array(Box::new(Type::Bool));
697 assert_eq!(format!("{}", ty), "bool[]");
698 }
699
700 #[test]
701 fn test_type_record() {
702 let mut fields = HashMap::new();
703 fields.insert("x".to_string(), Type::Int);
704 fields.insert("y".to_string(), Type::Int);
705 let ty = Type::Record(fields);
706 let display = format!("{}", ty);
707 assert!(display.contains("x: int"));
708 assert!(display.contains("y: int"));
709 }
710
711 #[test]
712 fn test_type_variant_simple() {
713 let ty = Type::Variant("Option".to_string(), vec![]);
714 assert_eq!(format!("{}", ty), "Option");
715 }
716
717 #[test]
718 fn test_type_variant_with_params() {
719 let ty = Type::Variant("Option".to_string(), vec![Type::Int]);
720 assert_eq!(format!("{}", ty), "Option<int>");
721 }
722
723 #[test]
724 fn test_type_function_multi() {
725 let ty = Type::function_multi(&[Type::Int, Type::Bool], Type::String);
726 assert_eq!(format!("{}", ty), "int -> bool -> string");
727 }
728
729 #[test]
734 fn test_free_vars_primitives() {
735 assert!(Type::Int.free_vars().is_empty());
736 assert!(Type::Bool.free_vars().is_empty());
737 assert!(Type::String.free_vars().is_empty());
738 assert!(Type::Unit.free_vars().is_empty());
739 }
740
741 #[test]
742 fn test_free_vars_var() {
743 let var = TypeVar::new(0, "a");
744 let ty = Type::Var(var.clone());
745 let free = ty.free_vars();
746 assert_eq!(free.len(), 1);
747 assert!(free.contains(&var));
748 }
749
750 #[test]
751 fn test_free_vars_function() {
752 let var_a = TypeVar::new(0, "a");
753 let var_b = TypeVar::new(1, "b");
754 let ty = Type::Function(
755 Box::new(Type::Var(var_a.clone())),
756 Box::new(Type::Var(var_b.clone())),
757 );
758 let free = ty.free_vars();
759 assert_eq!(free.len(), 2);
760 assert!(free.contains(&var_a));
761 assert!(free.contains(&var_b));
762 }
763
764 #[test]
765 fn test_free_vars_tuple() {
766 let var = TypeVar::new(0, "a");
767 let ty = Type::Tuple(vec![Type::Int, Type::Var(var.clone()), Type::Bool]);
768 let free = ty.free_vars();
769 assert_eq!(free.len(), 1);
770 assert!(free.contains(&var));
771 }
772
773 #[test]
774 fn test_free_vars_list() {
775 let var = TypeVar::new(0, "a");
776 let ty = Type::List(Box::new(Type::Var(var.clone())));
777 let free = ty.free_vars();
778 assert_eq!(free.len(), 1);
779 assert!(free.contains(&var));
780 }
781
782 #[test]
787 fn test_occurs_check_var_in_var() {
788 let var = TypeVar::new(0, "a");
789 let ty = Type::Var(var.clone());
790 assert!(ty.occurs_check(&var));
791 }
792
793 #[test]
794 fn test_occurs_check_var_not_in_primitive() {
795 let var = TypeVar::new(0, "a");
796 assert!(!Type::Int.occurs_check(&var));
797 assert!(!Type::Bool.occurs_check(&var));
798 }
799
800 #[test]
801 fn test_occurs_check_var_in_function() {
802 let var = TypeVar::new(0, "a");
803 let ty = Type::Function(Box::new(Type::Var(var.clone())), Box::new(Type::Int));
804 assert!(ty.occurs_check(&var));
805 }
806
807 #[test]
808 fn test_occurs_check_var_not_in_function() {
809 let var = TypeVar::new(0, "a");
810 let ty = Type::Function(Box::new(Type::Int), Box::new(Type::Bool));
811 assert!(!ty.occurs_check(&var));
812 }
813
814 #[test]
815 fn test_occurs_check_var_in_tuple() {
816 let var = TypeVar::new(0, "a");
817 let ty = Type::Tuple(vec![Type::Int, Type::Var(var.clone())]);
818 assert!(ty.occurs_check(&var));
819 }
820
821 #[test]
822 fn test_occurs_check_var_in_list() {
823 let var = TypeVar::new(0, "a");
824 let ty = Type::List(Box::new(Type::Var(var.clone())));
825 assert!(ty.occurs_check(&var));
826 }
827
828 #[test]
833 fn test_substitution_empty() {
834 let subst = Substitution::empty();
835 assert!(subst.is_empty());
836 assert_eq!(subst.len(), 0);
837 }
838
839 #[test]
840 fn test_substitution_singleton() {
841 let var = TypeVar::new(0, "a");
842 let subst = Substitution::singleton(var.clone(), Type::Int);
843 assert_eq!(subst.len(), 1);
844 assert_eq!(subst.lookup(&var), Some(Type::Int));
845 }
846
847 #[test]
848 fn test_substitution_lookup() {
849 let var = TypeVar::new(0, "a");
850 let subst = Substitution::singleton(var.clone(), Type::Int);
851 assert_eq!(subst.lookup(&var), Some(Type::Int));
852
853 let other_var = TypeVar::new(1, "b");
854 assert_eq!(subst.lookup(&other_var), None);
855 }
856
857 #[test]
858 fn test_substitution_apply_var() {
859 let var = TypeVar::new(0, "a");
860 let subst = Substitution::singleton(var.clone(), Type::Int);
861 let ty = Type::Var(var);
862 assert_eq!(subst.apply_type(&ty), Type::Int);
863 }
864
865 #[test]
866 fn test_substitution_apply_function() {
867 let var_a = TypeVar::new(0, "a");
868 let var_b = TypeVar::new(1, "b");
869 let mut subst = Substitution::empty();
870 subst.insert(var_a.clone(), Type::Int);
871 subst.insert(var_b.clone(), Type::Bool);
872
873 let ty = Type::Function(Box::new(Type::Var(var_a)), Box::new(Type::Var(var_b)));
874 let result = subst.apply_type(&ty);
875 assert_eq!(
876 result,
877 Type::Function(Box::new(Type::Int), Box::new(Type::Bool))
878 );
879 }
880
881 #[test]
882 fn test_substitution_compose_empty() {
883 let s1 = Substitution::empty();
884 let s2 = Substitution::empty();
885 let result = Substitution::compose(&s1, &s2);
886 assert!(result.is_empty());
887 }
888
889 #[test]
890 fn test_substitution_compose_basic() {
891 let var_a = TypeVar::new(0, "a");
892 let var_b = TypeVar::new(1, "b");
893
894 let s1 = Substitution::singleton(var_a.clone(), Type::Int);
895 let s2 = Substitution::singleton(var_b.clone(), Type::Var(var_a.clone()));
896
897 let result = Substitution::compose(&s1, &s2);
898
899 assert_eq!(result.lookup(&var_b), Some(Type::Int));
901 }
902
903 #[test]
904 fn test_substitution_display() {
905 let var = TypeVar::new(0, "a");
906 let subst = Substitution::singleton(var, Type::Int);
907 let display = format!("{}", subst);
908 assert!(display.contains("'a"));
909 assert!(display.contains("int"));
910 }
911
912 #[test]
917 fn test_typescheme_mono() {
918 let scheme = TypeScheme::mono(Type::Int);
919 assert!(scheme.is_mono());
920 assert_eq!(scheme.inner_type(), &Type::Int);
921 assert_eq!(format!("{}", scheme), "int");
922 }
923
924 #[test]
925 fn test_typescheme_poly() {
926 let var = TypeVar::new(0, "a");
927 let scheme = TypeScheme::poly(vec![var.clone()], Type::Var(var));
928 assert!(!scheme.is_mono());
929 assert_eq!(format!("{}", scheme), "∀'a. 'a");
930 }
931
932 #[test]
933 fn test_typescheme_free_vars_mono() {
934 let var = TypeVar::new(0, "a");
935 let scheme = TypeScheme::mono(Type::Var(var.clone()));
936 let free = scheme.free_vars();
937 assert_eq!(free.len(), 1);
938 assert!(free.contains(&var));
939 }
940
941 #[test]
942 fn test_typescheme_free_vars_poly() {
943 let var = TypeVar::new(0, "a");
944 let scheme = TypeScheme::poly(vec![var.clone()], Type::Var(var.clone()));
945 let free = scheme.free_vars();
946 assert!(free.is_empty()); }
948
949 #[test]
950 fn test_typescheme_apply() {
951 let var_a = TypeVar::new(0, "a");
952 let var_b = TypeVar::new(1, "b");
953 let scheme = TypeScheme::poly(
954 vec![var_a.clone()],
955 Type::Function(
956 Box::new(Type::Var(var_a.clone())),
957 Box::new(Type::Var(var_b.clone())),
958 ),
959 );
960
961 let subst = Substitution::singleton(var_b.clone(), Type::Int);
962 let result = scheme.apply(&subst);
963
964 assert_eq!(
966 result.ty,
967 Type::Function(Box::new(Type::Var(var_a)), Box::new(Type::Int))
968 );
969 }
970
971 #[test]
976 fn test_typeenv_new() {
977 let env = TypeEnv::new();
978 assert!(env.is_empty());
979 assert_eq!(env.len(), 0);
980 }
981
982 #[test]
983 fn test_typeenv_insert() {
984 let mut env = TypeEnv::new();
985 env.insert("x".to_string(), TypeScheme::mono(Type::Int));
986 assert_eq!(env.len(), 1);
987 assert!(env.lookup("x").is_some());
988 }
989
990 #[test]
991 fn test_typeenv_lookup() {
992 let mut env = TypeEnv::new();
993 env.insert("x".to_string(), TypeScheme::mono(Type::Int));
994 assert_eq!(env.lookup("x").unwrap().inner_type(), &Type::Int);
995 assert!(env.lookup("y").is_none());
996 }
997
998 #[test]
999 fn test_typeenv_extend() {
1000 let env1 = TypeEnv::new();
1001 let env2 = env1.extend("x".to_string(), TypeScheme::mono(Type::Int));
1002 assert!(env1.lookup("x").is_none());
1003 assert!(env2.lookup("x").is_some());
1004 }
1005
1006 #[test]
1007 fn test_typeenv_lookup_parent() {
1008 let mut env1 = TypeEnv::new();
1009 env1.insert("x".to_string(), TypeScheme::mono(Type::Int));
1010 let env2 = TypeEnv::with_parent(Rc::new(env1));
1011 assert!(env2.lookup("x").is_some());
1012 }
1013
1014 #[test]
1015 fn test_typeenv_free_vars() {
1016 let var = TypeVar::new(0, "a");
1017 let mut env = TypeEnv::new();
1018 env.insert("x".to_string(), TypeScheme::mono(Type::Var(var.clone())));
1019 let free = env.free_vars();
1020 assert_eq!(free.len(), 1);
1021 assert!(free.contains(&var));
1022 }
1023
1024 #[test]
1025 fn test_typeenv_generalize() {
1026 let var = TypeVar::new(0, "a");
1027 let env = TypeEnv::new();
1028 let scheme = env.generalize(&Type::Var(var.clone()));
1029 assert_eq!(scheme.vars.len(), 1);
1030 assert_eq!(scheme.vars[0], var);
1031 }
1032
1033 #[test]
1034 fn test_typeenv_generalize_with_env_vars() {
1035 let var_a = TypeVar::new(0, "a");
1036 let var_b = TypeVar::new(1, "b");
1037
1038 let mut env = TypeEnv::new();
1039 env.insert("x".to_string(), TypeScheme::mono(Type::Var(var_a.clone())));
1040
1041 let ty = Type::Function(
1043 Box::new(Type::Var(var_a.clone())),
1044 Box::new(Type::Var(var_b.clone())),
1045 );
1046 let scheme = env.generalize(&ty);
1047
1048 assert_eq!(scheme.vars.len(), 1);
1050 assert_eq!(scheme.vars[0], var_b);
1051 }
1052
1053 #[test]
1054 fn test_typeenv_instantiate() {
1055 let var = TypeVar::new(0, "a");
1056 let scheme = TypeScheme::poly(vec![var.clone()], Type::Var(var));
1057
1058 let env = TypeEnv::new();
1059 let mut counter = 100;
1060 let result = env.instantiate(&scheme, &mut || {
1061 counter += 1;
1062 TypeVar::fresh(counter)
1063 });
1064
1065 match result {
1067 Type::Var(v) => {
1068 assert_eq!(v.id, 101);
1069 assert_eq!(v.name, "t101");
1070 }
1071 _ => panic!("Expected type variable"),
1072 }
1073 }
1074
1075 #[test]
1076 fn test_typeenv_apply() {
1077 let var = TypeVar::new(0, "a");
1078 let mut env = TypeEnv::new();
1079 env.insert("x".to_string(), TypeScheme::mono(Type::Var(var.clone())));
1080
1081 let subst = Substitution::singleton(var, Type::Int);
1082 let new_env = env.apply(&subst);
1083
1084 assert_eq!(new_env.lookup("x").unwrap().inner_type(), &Type::Int);
1085 }
1086
1087 #[test]
1088 fn test_typeenv_bindings() {
1089 let mut env = TypeEnv::new();
1090 env.insert("x".to_string(), TypeScheme::mono(Type::Int));
1091 env.insert("y".to_string(), TypeScheme::mono(Type::Bool));
1092
1093 let bindings: Vec<_> = env.bindings().collect();
1094 assert_eq!(bindings.len(), 2);
1095 }
1096
1097 #[test]
1102 fn test_integration_simple_substitution() {
1103 let var = TypeVar::new(0, "a");
1104 let ty = Type::Function(
1105 Box::new(Type::Var(var.clone())),
1106 Box::new(Type::Var(var.clone())),
1107 );
1108 let subst = Substitution::singleton(var, Type::Int);
1109 let result = ty.apply(&subst);
1110 assert_eq!(
1111 result,
1112 Type::Function(Box::new(Type::Int), Box::new(Type::Int))
1113 );
1114 }
1115
1116 #[test]
1117 fn test_integration_generalize_instantiate() {
1118 let var = TypeVar::new(0, "a");
1119 let ty = Type::Var(var.clone());
1120
1121 let env = TypeEnv::new();
1122 let scheme = env.generalize(&ty);
1123
1124 let mut counter = 0;
1125 let result = env.instantiate(&scheme, &mut || {
1126 counter += 1;
1127 TypeVar::fresh(counter)
1128 });
1129
1130 match result {
1132 Type::Var(v) => assert_ne!(v.id, var.id),
1133 _ => panic!("Expected type variable"),
1134 }
1135 }
1136
1137 #[test]
1138 fn test_integration_complex_type() {
1139 let var = TypeVar::new(0, "a");
1141 let ty = Type::Function(
1142 Box::new(Type::Function(
1143 Box::new(Type::Int),
1144 Box::new(Type::Var(var.clone())),
1145 )),
1146 Box::new(Type::List(Box::new(Type::Var(var.clone())))),
1147 );
1148
1149 let free = ty.free_vars();
1150 assert_eq!(free.len(), 1);
1151 assert!(free.contains(&var));
1152
1153 let subst = Substitution::singleton(var, Type::Bool);
1154 let result = ty.apply(&subst);
1155
1156 assert_eq!(
1157 result,
1158 Type::Function(
1159 Box::new(Type::Function(Box::new(Type::Int), Box::new(Type::Bool))),
1160 Box::new(Type::List(Box::new(Type::Bool))),
1161 )
1162 );
1163 }
1164}