kodept_inference/
traits.rs1use std::borrow::Cow;
2use std::collections::HashSet;
3use std::fmt::Debug;
4use std::hash::Hash;
5
6use Constraint::{ExplicitInstance, ImplicitInstance};
7use MonomorphicType::{Constant, Pointer, Primitive, Tuple, Var};
8
9use crate::constraint::{Constraint, EqConstraint};
10use crate::constraint::Constraint::Eq;
11use crate::r#type::{MonomorphicType, PolymorphicType, TVar};
12use crate::r#type::MonomorphicType::Fn;
13use crate::substitution::Substitutions;
14
15pub(crate) trait Substitutable {
16 type Output;
17
18 fn substitute(&self, subst: &Substitutions) -> Self::Output;
19}
20
21pub(crate) trait FreeTypeVars {
22 fn free_types(self) -> HashSet<TVar>;
23}
24
25pub(crate) trait ActiveTVars {
26 fn active_vars(self) -> HashSet<TVar>;
27}
28
29pub trait EnvironmentProvider<Key: Hash + std::cmp::Eq> {
30 type Error;
31
32 #[deprecated]
33 fn get(&self, key: &Key) -> Option<Cow<PolymorphicType>> where Self::Error: Debug {
34 self.maybe_get(key).unwrap()
35 }
36
37 fn maybe_get(&self, key: &Key) -> Result<Option<Cow<PolymorphicType>>, Self::Error>;
38}
39
40impl Substitutable for TVar {
43 type Output = HashSet<TVar>;
44
45 fn substitute(&self, subst: &Substitutions) -> Self::Output {
46 subst.get(self).unwrap_or(&Var(*self)).free_types()
47 }
48}
49
50impl Substitutable for MonomorphicType {
51 type Output = Self;
52
53 fn substitute(&self, subst: &Substitutions) -> MonomorphicType {
54 match self {
55 Primitive(_) | Constant(_) => self.clone(),
56 Var(x) => subst.get(x).unwrap_or(self).clone(),
57 Fn(input, output) => Fn(
58 Box::new(input.substitute(subst)),
59 Box::new(output.substitute(subst)),
60 ),
61 Tuple(inner) => Tuple(crate::r#type::Tuple(inner.0.substitute(subst))),
62 Pointer(inner) => Pointer(Box::new(inner.substitute(subst))),
63 }
64 }
65}
66
67impl Substitutable for PolymorphicType {
68 type Output = Self;
69
70 fn substitute(&self, subst: &Substitutions) -> PolymorphicType {
71 let mut s = subst.clone();
72 self.bindings.iter().for_each(|it| s.remove(it));
73 Self {
74 bindings: self.bindings.clone(),
75 binding_type: self.binding_type.substitute(&s),
76 }
77 }
78}
79
80impl Substitutable for Constraint {
81 type Output = Self;
82
83 fn substitute(&self, subst: &Substitutions) -> Constraint {
84 match self {
85 Eq(EqConstraint { t1, t2 }) => Eq(EqConstraint {
86 t1: t1.substitute(subst),
87 t2: t2.substitute(subst),
88 }),
89 ExplicitInstance { t, s } => ExplicitInstance {
90 t: t.substitute(subst),
91 s: s.substitute(subst),
92 },
93 ImplicitInstance { t1, ctx, t2 } => ImplicitInstance {
94 t1: t1.substitute(subst),
95 ctx: ctx.substitute(subst),
96 t2: t2.substitute(subst),
97 },
98 }
99 }
100}
101
102impl<T: Substitutable> Substitutable for &T {
103 type Output = T::Output;
104
105 fn substitute(&self, subst: &Substitutions) -> Self::Output {
106 (*self).substitute(subst)
107 }
108}
109
110impl<T: Substitutable> Substitutable for [T] {
111 type Output = Vec<T::Output>;
112
113 fn substitute(&self, subst: &Substitutions) -> Self::Output {
114 self.iter().map(|it| it.substitute(subst)).collect()
115 }
116}
117
118impl<T: Substitutable<Output = HashSet<T>>> Substitutable for HashSet<T>
119where
120 T: Hash + std::cmp::Eq,
121{
122 type Output = HashSet<T>;
123
124 fn substitute(&self, subst: &Substitutions) -> Self::Output {
125 self.iter()
126 .flat_map(|it| it.substitute(subst))
127 .collect()
128 }
129}
130
131impl FreeTypeVars for &TVar {
134 fn free_types(self) -> HashSet<TVar> {
135 HashSet::from([*self])
136 }
137}
138
139impl FreeTypeVars for &MonomorphicType {
140 fn free_types(self) -> HashSet<TVar> {
141 match self {
142 Primitive(_) | Constant(_) => HashSet::new(),
143 Var(x) => HashSet::from([*x]),
144 Fn(input, output) => &input.free_types() | &output.free_types(),
145 Tuple(crate::r#type::Tuple(vec)) => vec.free_types(),
146 Pointer(x) => x.free_types(),
147 }
148 }
149}
150
151impl FreeTypeVars for &PolymorphicType {
152 fn free_types(self) -> HashSet<TVar> {
153 let mut free = self.binding_type.free_types();
154 self.bindings.iter().for_each(|it| {
155 free.remove(it);
156 });
157 free
158 }
159}
160
161impl<T: FreeTypeVars, I: IntoIterator<Item = T>> FreeTypeVars for I {
162 fn free_types(self) -> HashSet<TVar> {
163 self.into_iter()
164 .fold(HashSet::new(), |acc, next| &acc | &next.free_types())
165 }
166}
167
168impl ActiveTVars for &Constraint {
171 fn active_vars(self) -> HashSet<TVar> {
172 match self {
173 Eq(EqConstraint { t1, t2 }) => [t1.clone(), t2.clone()].free_types(),
174 ExplicitInstance { t, s } => &t.free_types() | &s.free_types(),
175 ImplicitInstance { t1, ctx, t2 } => {
176 let set = &ctx.free_types() & &t2.free_types();
177 &t1.free_types() | &set
178 }
179 }
180 }
181}
182
183impl<T: ActiveTVars, I: IntoIterator<Item = T>> ActiveTVars for I {
184 fn active_vars(self) -> HashSet<TVar> {
185 self.into_iter()
186 .fold(HashSet::new(), |acc, next| &acc | &next.active_vars())
187 }
188}