1use crate::{
2 env::Env, expr::ModPath, format_with_flags, PrintFlag, Rt, UserEvent, PRINT_FLAGS,
3};
4use anyhow::{anyhow, bail, Result};
5use arcstr::ArcStr;
6use enumflags2::BitFlags;
7use fxhash::{FxHashMap, FxHashSet};
8use netidx::{
9 publisher::{Typ, Value},
10 utils::Either,
11};
12use netidx_value::ValArray;
13use parking_lot::RwLock;
14use smallvec::{smallvec, SmallVec};
15use std::{
16 cell::RefCell,
17 cmp::{Eq, PartialEq},
18 collections::{hash_map::Entry, HashMap, HashSet},
19 fmt::{self, Debug},
20 iter,
21};
22use triomphe::Arc;
23
24mod fntyp;
25mod tval;
26mod tvar;
27
28pub use fntyp::{FnArgType, FnType};
29pub use tval::TVal;
30use tvar::would_cycle_inner;
31pub use tvar::TVar;
32
33struct AndAc(bool);
34
35impl FromIterator<bool> for AndAc {
36 fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
37 AndAc(iter.into_iter().all(|b| b))
38 }
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
42pub enum Type {
43 Bottom,
44 Any,
45 Primitive(BitFlags<Typ>),
46 Ref { scope: ModPath, name: ModPath, params: Arc<[Type]> },
47 Fn(Arc<FnType>),
48 Set(Arc<[Type]>),
49 TVar(TVar),
50 Array(Arc<Type>),
51 ByRef(Arc<Type>),
52 Tuple(Arc<[Type]>),
53 Struct(Arc<[(ArcStr, Type)]>),
54 Variant(ArcStr, Arc<[Type]>),
55}
56
57impl Default for Type {
58 fn default() -> Self {
59 Self::Bottom
60 }
61}
62
63impl Type {
64 pub fn empty_tvar() -> Self {
65 Type::TVar(TVar::default())
66 }
67
68 fn iter_prims(&self) -> impl Iterator<Item = Self> {
69 match self {
70 Self::Primitive(p) => {
71 Either::Left(p.iter().map(|t| Type::Primitive(t.into())))
72 }
73 t => Either::Right(iter::once(t.clone())),
74 }
75 }
76
77 pub fn is_defined(&self) -> bool {
78 match self {
79 Self::Bottom
80 | Self::Any
81 | Self::Primitive(_)
82 | Self::Fn(_)
83 | Self::Set(_)
84 | Self::Array(_)
85 | Self::ByRef(_)
86 | Self::Tuple(_)
87 | Self::Struct(_)
88 | Self::Variant(_, _) => true,
89 Self::TVar(tv) => tv.read().typ.read().is_some(),
90 Self::Ref { .. } => true,
91 }
92 }
93
94 pub fn lookup_ref<'a, R: Rt, E: UserEvent>(
95 &'a self,
96 env: &'a Env<R, E>,
97 ) -> Result<&'a Type> {
98 match self {
99 Self::Ref { scope, name, params } => {
100 let def = env
101 .lookup_typedef(scope, name)
102 .ok_or_else(|| anyhow!("undefined type {name} in {scope}"))?;
103 if def.params.len() != params.len() {
104 bail!("{} expects {} type parameters", name, def.params.len());
105 }
106 def.typ.unbind_tvars();
107 for ((tv, ct), arg) in def.params.iter().zip(params.iter()) {
108 if let Some(ct) = ct {
109 ct.check_contains(env, arg)?;
110 }
111 if !tv.would_cycle(arg) {
112 *tv.read().typ.write() = Some(arg.clone());
113 }
114 }
115 Ok(&def.typ)
116 }
117 t => Ok(t),
118 }
119 }
120
121 pub fn check_contains<R: Rt, E: UserEvent>(
122 &self,
123 env: &Env<R, E>,
124 t: &Self,
125 ) -> Result<()> {
126 if self.contains(env, t)? {
127 Ok(())
128 } else {
129 format_with_flags(PrintFlag::DerefTVars | PrintFlag::ReplacePrims, || {
130 bail!("type mismatch {self} does not contain {t}")
131 })
132 }
133 }
134
135 fn contains_int<R: Rt, E: UserEvent>(
136 &self,
137 env: &Env<R, E>,
138 hist: &mut FxHashMap<(usize, usize), bool>,
139 t: &Self,
140 ) -> Result<bool> {
141 if (self as *const Type) == (t as *const Type) {
142 return Ok(true);
143 }
144 match (self, t) {
145 (
146 Self::Ref { scope: s0, name: n0, .. },
147 Self::Ref { scope: s1, name: n1, .. },
148 ) if s0 == s1 && n0 == n1 => Ok(true),
149 (t0 @ Self::Ref { .. }, t1) | (t0, t1 @ Self::Ref { .. }) => {
150 let t0 = t0.lookup_ref(env)?;
151 let t1 = t1.lookup_ref(env)?;
152 let t0_addr = (t0 as *const Type).addr();
153 let t1_addr = (t1 as *const Type).addr();
154 match hist.get(&(t0_addr, t1_addr)) {
155 Some(r) => Ok(*r),
156 None => {
157 hist.insert((t0_addr, t1_addr), true);
158 match t0.contains_int(env, hist, t1) {
159 Ok(r) => {
160 hist.insert((t0_addr, t1_addr), r);
161 Ok(r)
162 }
163 Err(e) => {
164 hist.remove(&(t0_addr, t1_addr));
165 Err(e)
166 }
167 }
168 }
169 }
170 }
171 (Self::TVar(t0), Self::Bottom) => {
172 if let Some(_) = &*t0.read().typ.read() {
173 return Ok(true);
174 }
175 *t0.read().typ.write() = Some(Self::Bottom);
176 Ok(true)
177 }
178 (Self::TVar(t0), Self::Any) => {
179 if let Some(t0) = &*t0.read().typ.read() {
180 return t0.contains_int(env, hist, t);
181 }
182 *t0.read().typ.write() = Some(Self::Any);
183 Ok(true)
184 }
185 (Self::Any, _) => Ok(true),
186 (Self::Bottom, _) | (_, Self::Bottom) => Ok(true),
187 (Self::Primitive(p0), Self::Primitive(p1)) => Ok(p0.contains(*p1)),
188 (
189 Self::Primitive(p),
190 Self::Array(_) | Self::Tuple(_) | Self::Struct(_) | Self::Variant(_, _),
191 ) => Ok(p.contains(Typ::Array)),
192 (Self::Array(t0), Self::Array(t1)) => t0.contains_int(env, hist, t1),
193 (Self::Array(t0), Self::Primitive(p)) if *p == BitFlags::from(Typ::Array) => {
194 t0.contains_int(env, hist, &Type::Primitive(BitFlags::all()))
195 }
196 (Self::Tuple(t0), Self::Tuple(t1))
197 if t0.as_ptr().addr() == t1.as_ptr().addr() =>
198 {
199 Ok(true)
200 }
201 (Self::Tuple(t0), Self::Tuple(t1)) => Ok(t0.len() == t1.len()
202 && t0
203 .iter()
204 .zip(t1.iter())
205 .map(|(t0, t1)| t0.contains_int(env, hist, t1))
206 .collect::<Result<AndAc>>()?
207 .0),
208 (Self::Struct(t0), Self::Struct(t1))
209 if t0.as_ptr().addr() == t1.as_ptr().addr() =>
210 {
211 Ok(true)
212 }
213 (Self::Struct(t0), Self::Struct(t1)) => {
214 Ok(t0.len() == t1.len() && {
215 t0.iter()
217 .zip(t1.iter())
218 .map(|((n0, t0), (n1, t1))| {
219 Ok(n0 == n1 && t0.contains_int(env, hist, t1)?)
220 })
221 .collect::<Result<AndAc>>()?
222 .0
223 })
224 }
225 (Self::Variant(tg0, t0), Self::Variant(tg1, t1))
226 if tg0.as_ptr() == tg1.as_ptr()
227 && t0.as_ptr().addr() == t1.as_ptr().addr() =>
228 {
229 Ok(true)
230 }
231 (Self::Variant(tg0, t0), Self::Variant(tg1, t1)) => Ok(tg0 == tg1
232 && t0.len() == t1.len()
233 && t0
234 .iter()
235 .zip(t1.iter())
236 .map(|(t0, t1)| t0.contains_int(env, hist, t1))
237 .collect::<Result<AndAc>>()?
238 .0),
239 (Self::ByRef(t0), Self::ByRef(t1)) => t0.contains_int(env, hist, t1),
240 (Self::Tuple(_), Self::Array(_))
241 | (Self::Tuple(_), Self::Primitive(_))
242 | (Self::Tuple(_), Self::Struct(_))
243 | (Self::Tuple(_), Self::Variant(_, _))
244 | (Self::Array(_), Self::Primitive(_))
245 | (Self::Array(_), Self::Tuple(_))
246 | (Self::Array(_), Self::Struct(_))
247 | (Self::Array(_), Self::Variant(_, _))
248 | (Self::Struct(_), Self::Primitive(_))
249 | (Self::Struct(_), Self::Array(_))
250 | (Self::Struct(_), Self::Tuple(_))
251 | (Self::Struct(_), Self::Variant(_, _))
252 | (Self::Variant(_, _), Self::Array(_))
253 | (Self::Variant(_, _), Self::Struct(_))
254 | (Self::Variant(_, _), Self::Primitive(_))
255 | (Self::Variant(_, _), Self::Tuple(_)) => Ok(false),
256 (Self::TVar(t0), Self::TVar(t1)) if t0.addr() == t1.addr() => Ok(true),
257 (Self::TVar(t0), tt1 @ Self::TVar(t1)) => {
258 #[derive(Debug)]
259 enum Act {
260 RightCopy,
261 RightAlias,
262 LeftAlias,
263 LeftCopy,
264 }
265 let act = {
266 let t0 = t0.read();
267 let t1 = t1.read();
268 let addr = Arc::as_ptr(&t0.typ).addr();
269 if addr == Arc::as_ptr(&t1.typ).addr() {
270 return Ok(true);
271 }
272 let t0i = t0.typ.read();
273 let t1i = t1.typ.read();
274 match (&*t0i, &*t1i) {
275 (Some(t0), Some(t1)) => return t0.contains_int(env, hist, &*t1),
276 (None, None) => {
277 if would_cycle_inner(addr, tt1) {
278 return Ok(true);
279 }
280 if t0.frozen && t1.frozen {
281 return Ok(true);
282 }
283 if t0.frozen {
284 Act::RightAlias
285 } else {
286 Act::LeftAlias
287 }
288 }
289 (Some(_), None) => {
290 if would_cycle_inner(addr, tt1) {
291 return Ok(true);
292 }
293 Act::RightCopy
294 }
295 (None, Some(_)) => {
296 if would_cycle_inner(addr, tt1) {
297 return Ok(true);
298 }
299 Act::LeftCopy
300 }
301 }
302 };
303 match act {
304 Act::RightCopy => t1.copy(t0),
305 Act::RightAlias => t1.alias(t0),
306 Act::LeftAlias => t0.alias(t1),
307 Act::LeftCopy => t0.copy(t1),
308 }
309 Ok(true)
310 }
311 (Self::TVar(t0), t1) if !t0.would_cycle(t1) => {
312 if let Some(t0) = &*t0.read().typ.read() {
313 return t0.contains_int(env, hist, t1);
314 }
315 *t0.read().typ.write() = Some(t1.clone());
316 Ok(true)
317 }
318 (t0, Self::TVar(t1)) if !t1.would_cycle(t0) => {
319 if let Some(t1) = &*t1.read().typ.read() {
320 return t0.contains_int(env, hist, t1);
321 }
322 *t1.read().typ.write() = Some(t0.clone());
323 Ok(true)
324 }
325 (Self::Set(s0), Self::Set(s1))
326 if s0.as_ptr().addr() == s1.as_ptr().addr() =>
327 {
328 Ok(true)
329 }
330 (t0, Self::Set(s)) => Ok(s
331 .iter()
332 .map(|t1| t0.contains_int(env, hist, t1))
333 .collect::<Result<AndAc>>()?
334 .0),
335 (Self::Set(s), t) => Ok(s
336 .iter()
337 .fold(Ok::<_, anyhow::Error>(false), |acc, t0| {
338 Ok(acc? || t0.contains_int(env, hist, t)?)
339 })?
340 || t.iter_prims().fold(Ok::<_, anyhow::Error>(true), |acc, t1| {
341 Ok(acc?
342 && s.iter().fold(Ok::<_, anyhow::Error>(false), |acc, t0| {
343 Ok(acc? || t0.contains_int(env, hist, &t1)?)
344 })?)
345 })?),
346 (Self::Fn(f0), Self::Fn(f1)) => {
347 Ok(f0.as_ptr() == f1.as_ptr() || f0.contains_int(env, hist, f1)?)
348 }
349 (_, Self::Any)
350 | (_, Self::TVar(_))
351 | (Self::TVar(_), _)
352 | (Self::Fn(_), _)
353 | (Self::ByRef(_), _)
354 | (_, Self::ByRef(_))
355 | (_, Self::Fn(_)) => Ok(false),
356 }
357 }
358
359 pub fn contains<R: Rt, E: UserEvent>(
360 &self,
361 env: &Env<R, E>,
362 t: &Self,
363 ) -> Result<bool> {
364 thread_local! {
365 static HIST: RefCell<FxHashMap<(usize, usize), bool>> = RefCell::new(HashMap::default());
366 }
367 HIST.with_borrow_mut(|hist| {
368 hist.clear();
369 self.contains_int(env, hist, t)
370 })
371 }
372
373 fn could_match_int<R: Rt, E: UserEvent>(
374 &self,
375 env: &Env<R, E>,
376 hist: &mut FxHashMap<(usize, usize), bool>,
377 t: &Self,
378 ) -> Result<bool> {
379 match (self, t) {
380 (
381 Self::Ref { scope: s0, name: n0, .. },
382 Self::Ref { scope: s1, name: n1, .. },
383 ) if s0 == s1 && n0 == n1 => Ok(true),
384 (t0 @ Self::Ref { .. }, t1) | (t0, t1 @ Self::Ref { .. }) => {
385 let t0 = t0.lookup_ref(env)?;
386 let t1 = t1.lookup_ref(env)?;
387 let t0_addr = (t0 as *const Type).addr();
388 let t1_addr = (t1 as *const Type).addr();
389 match hist.get(&(t0_addr, t1_addr)) {
390 Some(r) => Ok(*r),
391 None => {
392 hist.insert((t0_addr, t1_addr), true);
393 match t0.could_match_int(env, hist, t1) {
394 Ok(r) => {
395 hist.insert((t0_addr, t1_addr), r);
396 Ok(r)
397 }
398 Err(e) => {
399 hist.remove(&(t0_addr, t1_addr));
400 Err(e)
401 }
402 }
403 }
404 }
405 }
406 (t0, Self::Primitive(s)) => {
407 for t1 in s.iter() {
408 if t0.contains_int(env, hist, &Type::Primitive(t1.into()))? {
409 return Ok(true);
410 }
411 }
412 Ok(false)
413 }
414 (t0, Self::Set(ts)) => {
415 for t1 in ts.iter() {
416 if t0.contains_int(env, hist, t1)? {
417 return Ok(true);
418 }
419 }
420 Ok(false)
421 }
422 (Type::TVar(t0), t1) => match &*t0.read().typ.read() {
423 Some(t0) => t0.could_match_int(env, hist, t1),
424 None => Ok(false),
425 },
426 (t0, Type::TVar(t1)) => match &*t1.read().typ.read() {
427 Some(t1) => t0.could_match_int(env, hist, t1),
428 None => Ok(false),
429 },
430 (t0, t1) => t0.contains_int(env, hist, t1),
431 }
432 }
433
434 pub fn could_match<R: Rt, E: UserEvent>(
435 &self,
436 env: &Env<R, E>,
437 t: &Self,
438 ) -> Result<bool> {
439 thread_local! {
440 static HIST: RefCell<FxHashMap<(usize, usize), bool>> = RefCell::new(HashMap::default());
441 }
442 HIST.with_borrow_mut(|hist| {
443 hist.clear();
444 self.could_match_int(env, hist, t)
445 })
446 }
447
448 fn union_int<R: Rt, E: UserEvent>(
449 &self,
450 env: &Env<R, E>,
451 hist: &mut FxHashMap<(usize, usize), Type>,
452 t: &Self,
453 ) -> Result<Self> {
454 match (self, t) {
455 (
456 Type::Ref { name: n0, scope: s0, .. },
457 Type::Ref { scope: s1, name: n1, .. },
458 ) if n0 == n1 && s0 == s1 => Ok(self.clone()),
459 (tr @ Type::Ref { .. }, t) => {
460 let t0 = tr.lookup_ref(env)?;
461 let t0_addr = (t0 as *const Type).addr();
462 let t_addr = (t as *const Type).addr();
463 match hist.get(&(t0_addr, t_addr)) {
464 Some(t) => Ok(t.clone()),
465 None => {
466 hist.insert((t0_addr, t_addr), tr.clone());
467 let r = t0.union_int(env, hist, t)?;
468 hist.insert((t0_addr, t_addr), r.clone());
469 Ok(r)
470 }
471 }
472 }
473 (t, tr @ Type::Ref { .. }) => {
474 let t1 = tr.lookup_ref(env)?;
475 let t1_addr = (t1 as *const Type).addr();
476 let t_addr = (t as *const Type).addr();
477 match hist.get(&(t_addr, t1_addr)) {
478 Some(t) => Ok(t.clone()),
479 None => {
480 hist.insert((t_addr, t1_addr), tr.clone());
481 let r = t.union_int(env, hist, t1)?;
482 hist.insert((t_addr, t1_addr), r.clone());
483 Ok(r)
484 }
485 }
486 }
487 (Type::Bottom, t) | (t, Type::Bottom) => Ok(t.clone()),
488 (Type::Any, _) | (_, Type::Any) => Ok(Type::Any),
489 (Type::Primitive(p), t) | (t, Type::Primitive(p)) if p.is_empty() => {
490 Ok(t.clone())
491 }
492 (Type::Primitive(s0), Type::Primitive(s1)) => {
493 let mut s = *s0;
494 s.insert(*s1);
495 Ok(Type::Primitive(s))
496 }
497 (
498 Type::Primitive(p),
499 Type::Array(_) | Type::Struct(_) | Type::Tuple(_) | Type::Variant(_, _),
500 )
501 | (
502 Type::Array(_) | Type::Struct(_) | Type::Tuple(_) | Type::Variant(_, _),
503 Type::Primitive(p),
504 ) if p.contains(Typ::Array) => Ok(Type::Primitive(*p)),
505 (Type::Primitive(p), Type::Array(t))
506 | (Type::Array(t), Type::Primitive(p)) => Ok(Type::Set(Arc::from_iter([
507 Type::Primitive(*p),
508 Type::Array(t.clone()),
509 ]))),
510 (t @ Type::Array(t0), u @ Type::Array(t1)) => {
511 if t0 == t1 {
512 Ok(Type::Array(t0.clone()))
513 } else {
514 Ok(Type::Set(Arc::from_iter([u.clone(), t.clone()])))
515 }
516 }
517 (t @ Type::ByRef(t0), u @ Type::ByRef(t1)) => {
518 if t0 == t1 {
519 Ok(Type::ByRef(t0.clone()))
520 } else {
521 Ok(Type::Set(Arc::from_iter([u.clone(), t.clone()])))
522 }
523 }
524 (Type::Set(s0), Type::Set(s1)) => Ok(Type::Set(Arc::from_iter(
525 s0.iter().cloned().chain(s1.iter().cloned()),
526 ))),
527 (Type::Set(s), t) | (t, Type::Set(s)) => Ok(Type::Set(Arc::from_iter(
528 s.iter().cloned().chain(iter::once(t.clone())),
529 ))),
530 (u @ Type::Struct(t0), t @ Type::Struct(t1)) => {
531 if t0.len() == t1.len() && t0 == t1 {
532 Ok(u.clone())
533 } else {
534 Ok(Type::Set(Arc::from_iter([u.clone(), t.clone()])))
535 }
536 }
537 (u @ Type::Struct(_), t) | (t, u @ Type::Struct(_)) => {
538 Ok(Type::Set(Arc::from_iter([u.clone(), t.clone()])))
539 }
540 (u @ Type::Tuple(t0), t @ Type::Tuple(t1)) => {
541 if t0 == t1 {
542 Ok(u.clone())
543 } else {
544 Ok(Type::Set(Arc::from_iter([u.clone(), t.clone()])))
545 }
546 }
547 (u @ Type::Tuple(_), t) | (t, u @ Type::Tuple(_)) => {
548 Ok(Type::Set(Arc::from_iter([u.clone(), t.clone()])))
549 }
550 (u @ Type::Variant(tg0, t0), t @ Type::Variant(tg1, t1)) => {
551 if tg0 == tg1 && t0.len() == t1.len() {
552 let typs = t0
553 .iter()
554 .zip(t1.iter())
555 .map(|(t0, t1)| t0.union_int(env, hist, t1))
556 .collect::<Result<SmallVec<[_; 8]>>>()?;
557 Ok(Type::Variant(tg0.clone(), Arc::from_iter(typs.into_iter())))
558 } else {
559 Ok(Type::Set(Arc::from_iter([u.clone(), t.clone()])))
560 }
561 }
562 (u @ Type::Variant(_, _), t) | (t, u @ Type::Variant(_, _)) => {
563 Ok(Type::Set(Arc::from_iter([u.clone(), t.clone()])))
564 }
565 (Type::Fn(f0), Type::Fn(f1)) => {
566 if f0 == f1 {
567 Ok(Type::Fn(f0.clone()))
568 } else {
569 Ok(Type::Set(Arc::from_iter([
570 Type::Fn(f0.clone()),
571 Type::Fn(f1.clone()),
572 ])))
573 }
574 }
575 (f @ Type::Fn(_), t) | (t, f @ Type::Fn(_)) => {
576 Ok(Type::Set(Arc::from_iter([f.clone(), t.clone()])))
577 }
578 (t0 @ Type::TVar(_), t1 @ Type::TVar(_)) => {
579 if t0 == t1 {
580 Ok(t0.clone())
581 } else {
582 Ok(Type::Set(Arc::from_iter([t0.clone(), t1.clone()])))
583 }
584 }
585 (t0 @ Type::TVar(_), t1) | (t1, t0 @ Type::TVar(_)) => {
586 Ok(Type::Set(Arc::from_iter([t0.clone(), t1.clone()])))
587 }
588 (t @ Type::ByRef(_), u) | (u, t @ Type::ByRef(_)) => {
589 Ok(Type::Set(Arc::from_iter([t.clone(), u.clone()])))
590 }
591 }
592 }
593
594 pub fn union<R: Rt, E: UserEvent>(&self, env: &Env<R, E>, t: &Self) -> Result<Self> {
595 thread_local! {
596 static HIST: RefCell<FxHashMap<(usize, usize), Type>> = RefCell::new(HashMap::default());
597 }
598 HIST.with_borrow_mut(|hist| {
599 hist.clear();
600 Ok(self.union_int(env, hist, t)?.normalize())
601 })
602 }
603
604 fn diff_int<R: Rt, E: UserEvent>(
605 &self,
606 env: &Env<R, E>,
607 hist: &mut FxHashMap<(usize, usize), Type>,
608 t: &Self,
609 ) -> Result<Self> {
610 match (self, t) {
611 (Type::Any, _) => Ok(Type::Any),
612 (_, Type::Any) => Ok(Type::Primitive(BitFlags::empty())),
613 (
614 Type::Ref { scope: s0, name: n0, .. },
615 Type::Ref { scope: s1, name: n1, .. },
616 ) if s0 == s1 && n0 == n1 => Ok(Type::Primitive(BitFlags::empty())),
617 (t0 @ Type::Ref { .. }, t1) | (t0, t1 @ Type::Ref { .. }) => {
618 let t0 = t0.lookup_ref(env)?;
619 let t1 = t1.lookup_ref(env)?;
620 let t0_addr = (t0 as *const Type).addr();
621 let t1_addr = (t1 as *const Type).addr();
622 match hist.get(&(t0_addr, t1_addr)) {
623 Some(r) => Ok(r.clone()),
624 None => {
625 let r = Type::Primitive(BitFlags::empty());
626 hist.insert((t0_addr, t1_addr), r);
627 match t0.diff_int(env, hist, &t1) {
628 Ok(r) => {
629 hist.insert((t0_addr, t1_addr), r.clone());
630 Ok(r)
631 }
632 Err(e) => {
633 hist.remove(&(t0_addr, t1_addr));
634 Err(e)
635 }
636 }
637 }
638 }
639 }
640 (Type::Bottom, t) | (t, Type::Bottom) => Ok(t.clone()),
641 (Type::Primitive(s0), Type::Primitive(s1)) => {
642 let mut s = *s0;
643 s.remove(*s1);
644 Ok(Type::Primitive(s))
645 }
646 (
647 Type::Primitive(p),
648 Type::Array(_) | Type::Struct(_) | Type::Tuple(_) | Type::Variant(_, _),
649 ) => {
650 let mut s = *p;
652 s.remove(Typ::Array);
653 Ok(Type::Primitive(s))
654 }
655 (
656 Type::Array(_) | Type::Struct(_) | Type::Tuple(_) | Type::Variant(_, _),
657 Type::Primitive(p),
658 ) => {
659 if p.contains(Typ::Array) {
660 Ok(Type::Primitive(BitFlags::empty()))
661 } else {
662 Ok(self.clone())
663 }
664 }
665 (Type::Array(t0), Type::Array(t1)) => {
666 if t0 == t1 {
667 Ok(Type::Primitive(BitFlags::empty()))
668 } else {
669 Ok(Type::Array(Arc::new(t0.diff_int(env, hist, t1)?)))
670 }
671 }
672 (Type::ByRef(t0), Type::ByRef(t1)) => {
673 Ok(Type::ByRef(Arc::new(t0.diff_int(env, hist, t1)?)))
674 }
675 (Type::Set(s0), Type::Set(s1)) => {
676 let mut s: SmallVec<[Type; 4]> = smallvec![];
677 for i in 0..s0.len() {
678 s.push(s0[i].clone());
679 for j in 0..s1.len() {
680 s[i] = s[i].diff_int(env, hist, &s1[j])?
681 }
682 }
683 Ok(Self::flatten_set(s.into_iter()))
684 }
685 (Type::Set(s), t) => Ok(Self::flatten_set(
686 s.iter()
687 .map(|s| s.diff_int(env, hist, t))
688 .collect::<Result<SmallVec<[_; 8]>>>()?,
689 )),
690 (t, Type::Set(s)) => {
691 let mut t = t.clone();
692 for st in s.iter() {
693 t = t.diff_int(env, hist, st)?;
694 }
695 Ok(t)
696 }
697 (Type::Tuple(t0), Type::Tuple(t1)) => {
698 if t0 == t1 {
699 Ok(Type::Primitive(BitFlags::empty()))
700 } else {
701 Ok(self.clone())
702 }
703 }
704 (Type::Tuple(_), _) | (_, Type::Tuple(_)) => Ok(self.clone()),
705 (Type::Struct(t0), Type::Struct(t1)) => {
706 if t0.len() == t1.len() && t0 == t1 {
707 Ok(Type::Primitive(BitFlags::empty()))
708 } else {
709 Ok(self.clone())
710 }
711 }
712 (Type::Struct(_), _) | (_, Type::Struct(_)) => Ok(self.clone()),
713 (Type::ByRef(_), _) | (_, Type::ByRef(_)) => Ok(self.clone()),
714 (Type::Variant(tg0, t0), Type::Variant(tg1, t1)) => {
715 if tg0 == tg1 && t0.len() == t1.len() && t0 == t1 {
716 Ok(Type::Primitive(BitFlags::empty()))
717 } else {
718 Ok(self.clone())
719 }
720 }
721 (Type::Variant(_, _), _) | (_, Type::Variant(_, _)) => Ok(self.clone()),
722 (Type::Fn(f0), Type::Fn(f1)) => {
723 if f0 == f1 {
724 Ok(Type::Primitive(BitFlags::empty()))
725 } else {
726 Ok(Type::Fn(f0.clone()))
727 }
728 }
729 (f @ Type::Fn(_), _) => Ok(f.clone()),
730 (t, Type::Fn(_)) => Ok(t.clone()),
731 (Type::TVar(tv0), Type::TVar(tv1)) => {
732 if tv0.read().typ.as_ptr() == tv1.read().typ.as_ptr() {
733 return Ok(Type::Primitive(BitFlags::empty()));
734 }
735 Ok(match (&*tv0.read().typ.read(), &*tv1.read().typ.read()) {
736 (None, _) | (_, None) => Type::TVar(tv0.clone()),
737 (Some(t0), Some(t1)) => t0.diff_int(env, hist, t1)?,
738 })
739 }
740 (Type::TVar(tv), t1) => match &*tv.read().typ.read() {
741 None => Ok(Type::TVar(tv.clone())),
742 Some(t0) => t0.diff_int(env, hist, t1),
743 },
744 (t0, Type::TVar(tv)) => match &*tv.read().typ.read() {
745 None => Ok(t0.clone()),
746 Some(t1) => t0.diff_int(env, hist, t1),
747 },
748 }
749 }
750
751 pub fn diff<R: Rt, E: UserEvent>(&self, env: &Env<R, E>, t: &Self) -> Result<Self> {
752 thread_local! {
753 static HIST: RefCell<FxHashMap<(usize, usize), Type>> = RefCell::new(HashMap::default());
754 }
755 HIST.with_borrow_mut(|hist| {
756 hist.clear();
757 Ok(self.diff_int(env, hist, t)?.normalize())
758 })
759 }
760
761 pub fn any() -> Self {
762 Self::Any
763 }
764
765 pub fn boolean() -> Self {
766 Self::Primitive(Typ::Bool.into())
767 }
768
769 pub fn number() -> Self {
770 Self::Primitive(Typ::number())
771 }
772
773 pub fn int() -> Self {
774 Self::Primitive(Typ::integer())
775 }
776
777 pub fn uint() -> Self {
778 Self::Primitive(Typ::unsigned_integer())
779 }
780
781 pub fn alias_tvars(&self, known: &mut FxHashMap<ArcStr, TVar>) {
783 match self {
784 Type::Bottom | Type::Any | Type::Primitive(_) => (),
785 Type::Ref { params, .. } => {
786 for t in params.iter() {
787 t.alias_tvars(known);
788 }
789 }
790 Type::Array(t) => t.alias_tvars(known),
791 Type::ByRef(t) => t.alias_tvars(known),
792 Type::Tuple(ts) => {
793 for t in ts.iter() {
794 t.alias_tvars(known)
795 }
796 }
797 Type::Struct(ts) => {
798 for (_, t) in ts.iter() {
799 t.alias_tvars(known)
800 }
801 }
802 Type::Variant(_, ts) => {
803 for t in ts.iter() {
804 t.alias_tvars(known)
805 }
806 }
807 Type::TVar(tv) => match known.entry(tv.name.clone()) {
808 Entry::Occupied(e) => {
809 let v = e.get();
810 v.freeze();
811 tv.alias(v);
812 }
813 Entry::Vacant(e) => {
814 e.insert(tv.clone());
815 ()
816 }
817 },
818 Type::Fn(ft) => ft.alias_tvars(known),
819 Type::Set(s) => {
820 for typ in s.iter() {
821 typ.alias_tvars(known)
822 }
823 }
824 }
825 }
826
827 pub fn collect_tvars(&self, known: &mut FxHashMap<ArcStr, TVar>) {
828 match self {
829 Type::Bottom | Type::Any | Type::Primitive(_) => (),
830 Type::Ref { params, .. } => {
831 for t in params.iter() {
832 t.collect_tvars(known);
833 }
834 }
835 Type::Array(t) => t.collect_tvars(known),
836 Type::ByRef(t) => t.collect_tvars(known),
837 Type::Tuple(ts) => {
838 for t in ts.iter() {
839 t.collect_tvars(known)
840 }
841 }
842 Type::Struct(ts) => {
843 for (_, t) in ts.iter() {
844 t.collect_tvars(known)
845 }
846 }
847 Type::Variant(_, ts) => {
848 for t in ts.iter() {
849 t.collect_tvars(known)
850 }
851 }
852 Type::TVar(tv) => match known.entry(tv.name.clone()) {
853 Entry::Occupied(_) => (),
854 Entry::Vacant(e) => {
855 e.insert(tv.clone());
856 ()
857 }
858 },
859 Type::Fn(ft) => ft.collect_tvars(known),
860 Type::Set(s) => {
861 for typ in s.iter() {
862 typ.collect_tvars(known)
863 }
864 }
865 }
866 }
867
868 pub fn check_tvars_declared(&self, declared: &FxHashSet<ArcStr>) -> Result<()> {
869 match self {
870 Type::Bottom | Type::Any | Type::Primitive(_) => Ok(()),
871 Type::Ref { params, .. } => {
872 params.iter().try_for_each(|t| t.check_tvars_declared(declared))
873 }
874 Type::Array(t) => t.check_tvars_declared(declared),
875 Type::ByRef(t) => t.check_tvars_declared(declared),
876 Type::Tuple(ts) => {
877 ts.iter().try_for_each(|t| t.check_tvars_declared(declared))
878 }
879 Type::Struct(ts) => {
880 ts.iter().try_for_each(|(_, t)| t.check_tvars_declared(declared))
881 }
882 Type::Variant(_, ts) => {
883 ts.iter().try_for_each(|t| t.check_tvars_declared(declared))
884 }
885 Type::TVar(tv) => {
886 if !declared.contains(&tv.name) {
887 bail!("undeclared type variable '{}'", tv.name)
888 } else {
889 Ok(())
890 }
891 }
892 Type::Set(s) => s.iter().try_for_each(|t| t.check_tvars_declared(declared)),
893 Type::Fn(_) => Ok(()),
894 }
895 }
896
897 pub fn has_unbound(&self) -> bool {
898 match self {
899 Type::Bottom | Type::Any | Type::Primitive(_) => false,
900 Type::Ref { .. } => false,
901 Type::Array(t0) => t0.has_unbound(),
902 Type::ByRef(t0) => t0.has_unbound(),
903 Type::Tuple(ts) => ts.iter().any(|t| t.has_unbound()),
904 Type::Struct(ts) => ts.iter().any(|(_, t)| t.has_unbound()),
905 Type::Variant(_, ts) => ts.iter().any(|t| t.has_unbound()),
906 Type::TVar(tv) => tv.read().typ.read().is_some(),
907 Type::Set(s) => s.iter().any(|t| t.has_unbound()),
908 Type::Fn(ft) => ft.has_unbound(),
909 }
910 }
911
912 pub fn bind_as(&self, t: &Self) {
914 match self {
915 Type::Bottom | Type::Any | Type::Primitive(_) => (),
916 Type::Ref { .. } => (),
917 Type::Array(t0) => t0.bind_as(t),
918 Type::ByRef(t0) => t0.bind_as(t),
919 Type::Tuple(ts) => {
920 for elt in ts.iter() {
921 elt.bind_as(t)
922 }
923 }
924 Type::Struct(ts) => {
925 for (_, elt) in ts.iter() {
926 elt.bind_as(t)
927 }
928 }
929 Type::Variant(_, ts) => {
930 for elt in ts.iter() {
931 elt.bind_as(t)
932 }
933 }
934 Type::TVar(tv) => {
935 let tv = tv.read();
936 let mut tv = tv.typ.write();
937 if tv.is_none() {
938 *tv = Some(t.clone());
939 }
940 }
941 Type::Set(s) => {
942 for elt in s.iter() {
943 elt.bind_as(t)
944 }
945 }
946 Type::Fn(ft) => ft.bind_as(t),
947 }
948 }
949
950 pub fn reset_tvars(&self) -> Type {
953 match self {
954 Type::Bottom => Type::Bottom,
955 Type::Any => Type::Any,
956 Type::Primitive(p) => Type::Primitive(*p),
957 Type::Ref { scope, name, params } => Type::Ref {
958 scope: scope.clone(),
959 name: name.clone(),
960 params: Arc::from_iter(params.iter().map(|t| t.reset_tvars())),
961 },
962 Type::Array(t0) => Type::Array(Arc::new(t0.reset_tvars())),
963 Type::ByRef(t0) => Type::ByRef(Arc::new(t0.reset_tvars())),
964 Type::Tuple(ts) => {
965 Type::Tuple(Arc::from_iter(ts.iter().map(|t| t.reset_tvars())))
966 }
967 Type::Struct(ts) => Type::Struct(Arc::from_iter(
968 ts.iter().map(|(n, t)| (n.clone(), t.reset_tvars())),
969 )),
970 Type::Variant(tag, ts) => Type::Variant(
971 tag.clone(),
972 Arc::from_iter(ts.iter().map(|t| t.reset_tvars())),
973 ),
974 Type::TVar(tv) => Type::TVar(TVar::empty_named(tv.name.clone())),
975 Type::Set(s) => Type::Set(Arc::from_iter(s.iter().map(|t| t.reset_tvars()))),
976 Type::Fn(fntyp) => Type::Fn(Arc::new(fntyp.reset_tvars())),
977 }
978 }
979
980 pub fn replace_tvars(&self, known: &FxHashMap<ArcStr, Self>) -> Type {
983 match self {
984 Type::TVar(tv) => match known.get(&tv.name) {
985 Some(t) => t.clone(),
986 None => Type::TVar(tv.clone()),
987 },
988 Type::Bottom => Type::Bottom,
989 Type::Any => Type::Any,
990 Type::Primitive(p) => Type::Primitive(*p),
991 Type::Ref { scope, name, params } => Type::Ref {
992 scope: scope.clone(),
993 name: name.clone(),
994 params: Arc::from_iter(params.iter().map(|t| t.replace_tvars(known))),
995 },
996 Type::Array(t0) => Type::Array(Arc::new(t0.replace_tvars(known))),
997 Type::ByRef(t0) => Type::ByRef(Arc::new(t0.replace_tvars(known))),
998 Type::Tuple(ts) => {
999 Type::Tuple(Arc::from_iter(ts.iter().map(|t| t.replace_tvars(known))))
1000 }
1001 Type::Struct(ts) => Type::Struct(Arc::from_iter(
1002 ts.iter().map(|(n, t)| (n.clone(), t.replace_tvars(known))),
1003 )),
1004 Type::Variant(tag, ts) => Type::Variant(
1005 tag.clone(),
1006 Arc::from_iter(ts.iter().map(|t| t.replace_tvars(known))),
1007 ),
1008 Type::Set(s) => {
1009 Type::Set(Arc::from_iter(s.iter().map(|t| t.replace_tvars(known))))
1010 }
1011 Type::Fn(fntyp) => Type::Fn(Arc::new(fntyp.replace_tvars(known))),
1012 }
1013 }
1014
1015 pub(crate) fn unbind_tvars(&self) {
1017 match self {
1018 Type::Bottom | Type::Any | Type::Primitive(_) | Type::Ref { .. } => (),
1019 Type::Array(t0) => t0.unbind_tvars(),
1020 Type::ByRef(t0) => t0.unbind_tvars(),
1021 Type::Tuple(ts) | Type::Variant(_, ts) | Type::Set(ts) => {
1022 for t in ts.iter() {
1023 t.unbind_tvars()
1024 }
1025 }
1026 Type::Struct(ts) => {
1027 for (_, t) in ts.iter() {
1028 t.unbind_tvars()
1029 }
1030 }
1031 Type::TVar(tv) => tv.unbind(),
1032 Type::Fn(fntyp) => fntyp.unbind_tvars(),
1033 }
1034 }
1035
1036 fn first_prim_int<R: Rt, E: UserEvent>(
1037 &self,
1038 env: &Env<R, E>,
1039 hist: &mut FxHashSet<usize>,
1040 ) -> Option<Typ> {
1041 match self {
1042 Type::Primitive(p) => p.iter().next(),
1043 Type::Set(s) => s.iter().find_map(|t| t.first_prim_int(env, hist)),
1044 Type::TVar(tv) => {
1045 tv.read().typ.read().as_ref().and_then(|t| t.first_prim_int(env, hist))
1046 }
1047 Type::Bottom
1049 | Type::Any
1050 | Type::Fn(_)
1051 | Type::Array(_)
1052 | Type::Tuple(_)
1053 | Type::Struct(_)
1054 | Type::Variant(_, _)
1055 | Type::ByRef(_) => None,
1056 Type::Ref { .. } => {
1057 let t = self.lookup_ref(env).ok()?;
1058 let t_addr = (t as *const Type).addr();
1059 if hist.contains(&t_addr) {
1060 None
1061 } else {
1062 hist.insert(t_addr);
1063 t.first_prim_int(env, hist)
1064 }
1065 }
1066 }
1067 }
1068
1069 fn first_prim<R: Rt, E: UserEvent>(&self, env: &Env<R, E>) -> Option<Typ> {
1070 thread_local! {
1071 static HIST: RefCell<FxHashSet<usize>> = RefCell::new(HashSet::default());
1072 }
1073 HIST.with_borrow_mut(|hist| {
1074 hist.clear();
1075 self.first_prim_int(env, hist)
1076 })
1077 }
1078
1079 fn check_cast_int<R: Rt, E: UserEvent>(
1080 &self,
1081 env: &Env<R, E>,
1082 hist: &mut FxHashSet<usize>,
1083 ) -> Result<()> {
1084 match self {
1085 Type::Primitive(_) | Type::Any => Ok(()),
1086 Type::Fn(_) => bail!("can't cast a value to a function"),
1087 Type::Bottom => bail!("can't cast a value to bottom"),
1088 Type::Set(s) => Ok(for t in s.iter() {
1089 t.check_cast_int(env, hist)?
1090 }),
1091 Type::TVar(tv) => match &*tv.read().typ.read() {
1092 Some(t) => t.check_cast_int(env, hist),
1093 None => bail!("can't cast a value to a free type variable"),
1094 },
1095 Type::Array(et) => et.check_cast_int(env, hist),
1096 Type::ByRef(_) => bail!("can't cast a reference"),
1097 Type::Tuple(ts) => Ok(for t in ts.iter() {
1098 t.check_cast_int(env, hist)?
1099 }),
1100 Type::Struct(ts) => Ok(for (_, t) in ts.iter() {
1101 t.check_cast_int(env, hist)?
1102 }),
1103 Type::Variant(_, ts) => Ok(for t in ts.iter() {
1104 t.check_cast_int(env, hist)?
1105 }),
1106 Type::Ref { .. } => {
1107 let t = self.lookup_ref(env)?;
1108 let t_addr = (t as *const Type).addr();
1109 if hist.contains(&t_addr) {
1110 Ok(())
1111 } else {
1112 hist.insert(t_addr);
1113 t.check_cast_int(env, hist)
1114 }
1115 }
1116 }
1117 }
1118
1119 pub fn check_cast<R: Rt, E: UserEvent>(&self, env: &Env<R, E>) -> Result<()> {
1120 thread_local! {
1121 static HIST: RefCell<FxHashSet<usize>> = RefCell::new(FxHashSet::default());
1122 }
1123 HIST.with_borrow_mut(|hist| {
1124 hist.clear();
1125 self.check_cast_int(env, hist)
1126 })
1127 }
1128
1129 fn cast_value_int<R: Rt, E: UserEvent>(
1130 &self,
1131 env: &Env<R, E>,
1132 hist: &mut FxHashSet<usize>,
1133 v: Value,
1134 ) -> Result<Value> {
1135 if self.is_a_int(env, hist, &v) {
1136 return Ok(v);
1137 }
1138 match self {
1139 Type::Array(et) => match v {
1140 Value::Array(elts) => {
1141 let va = elts
1142 .iter()
1143 .map(|el| et.cast_value_int(env, hist, el.clone()))
1144 .collect::<Result<SmallVec<[Value; 8]>>>()?;
1145 Ok(Value::Array(ValArray::from_iter_exact(va.into_iter())))
1146 }
1147 v => Ok(Value::Array([et.cast_value_int(env, hist, v)?].into())),
1148 },
1149 Type::Tuple(ts) => match v {
1150 Value::Array(elts) => {
1151 if elts.len() != ts.len() {
1152 bail!("tuple size mismatch {self} with {}", Value::Array(elts))
1153 }
1154 let a = ts
1155 .iter()
1156 .zip(elts.iter())
1157 .map(|(t, el)| t.cast_value_int(env, hist, el.clone()))
1158 .collect::<Result<SmallVec<[Value; 8]>>>()?;
1159 Ok(Value::Array(ValArray::from_iter_exact(a.into_iter())))
1160 }
1161 v => bail!("can't cast {v} to {self}"),
1162 },
1163 Type::Struct(ts) => match v {
1164 Value::Array(elts) => {
1165 if elts.len() != ts.len() {
1166 bail!("struct size mismatch {self} with {}", Value::Array(elts))
1167 }
1168 let is_pairs = elts.iter().all(|v| match v {
1169 Value::Array(a) if a.len() == 2 => match &a[0] {
1170 Value::String(_) => true,
1171 _ => false,
1172 },
1173 _ => false,
1174 });
1175 if !is_pairs {
1176 bail!("expected array of pairs, got {}", Value::Array(elts))
1177 }
1178 let mut elts_s: SmallVec<[&Value; 16]> = elts.iter().collect();
1179 elts_s.sort_by_key(|v| match v {
1180 Value::Array(a) => match &a[0] {
1181 Value::String(s) => s,
1182 _ => unreachable!(),
1183 },
1184 _ => unreachable!(),
1185 });
1186 let (keys_ok, ok) = ts.iter().zip(elts_s.iter()).fold(
1187 Ok((true, true)),
1188 |acc: Result<_>, ((fname, t), v)| {
1189 let (kok, ok) = acc?;
1190 let (name, v) = match v {
1191 Value::Array(a) => match (&a[0], &a[1]) {
1192 (Value::String(n), v) => (n, v),
1193 _ => unreachable!(),
1194 },
1195 _ => unreachable!(),
1196 };
1197 Ok((
1198 kok && name == fname,
1199 ok && kok
1200 && t.contains(
1201 env,
1202 &Type::Primitive(Typ::get(v).into()),
1203 )?,
1204 ))
1205 },
1206 )?;
1207 if ok {
1208 drop(elts_s);
1209 return Ok(Value::Array(elts));
1210 } else if keys_ok {
1211 let elts = ts
1212 .iter()
1213 .zip(elts_s.iter())
1214 .map(|((n, t), v)| match v {
1215 Value::Array(a) => {
1216 let a = [
1217 Value::String(n.clone()),
1218 t.cast_value_int(env, hist, a[1].clone())?,
1219 ];
1220 Ok(Value::Array(ValArray::from_iter_exact(
1221 a.into_iter(),
1222 )))
1223 }
1224 _ => unreachable!(),
1225 })
1226 .collect::<Result<SmallVec<[Value; 8]>>>()?;
1227 Ok(Value::Array(ValArray::from_iter_exact(elts.into_iter())))
1228 } else {
1229 drop(elts_s);
1230 bail!("struct fields mismatch {self}, {}", Value::Array(elts))
1231 }
1232 }
1233 v => bail!("can't cast {v} to {self}"),
1234 },
1235 Type::Variant(tag, ts) if ts.len() == 0 => match &v {
1236 Value::String(s) if s == tag => Ok(v),
1237 _ => bail!("variant tag mismatch expected {tag} got {v}"),
1238 },
1239 Type::Variant(tag, ts) => match &v {
1240 Value::Array(elts) => {
1241 if ts.len() + 1 == elts.len() {
1242 match &elts[0] {
1243 Value::String(s) if s == tag => (),
1244 v => bail!("variant tag mismatch expected {tag} got {v}"),
1245 }
1246 let a = iter::once(&Type::Primitive(Typ::String.into()))
1247 .chain(ts.iter())
1248 .zip(elts.iter())
1249 .map(|(t, v)| t.cast_value_int(env, hist, v.clone()))
1250 .collect::<Result<SmallVec<[Value; 8]>>>()?;
1251 Ok(Value::Array(ValArray::from_iter_exact(a.into_iter())))
1252 } else if ts.len() == elts.len() {
1253 let mut a = ts
1254 .iter()
1255 .zip(elts.iter())
1256 .map(|(t, v)| t.cast_value_int(env, hist, v.clone()))
1257 .collect::<Result<SmallVec<[Value; 8]>>>()?;
1258 a.insert(0, Value::String(tag.clone()));
1259 Ok(Value::Array(ValArray::from_iter_exact(a.into_iter())))
1260 } else {
1261 bail!("variant length mismatch")
1262 }
1263 }
1264 v => bail!("can't cast {v} to {self}"),
1265 },
1266 Type::Ref { .. } => self.lookup_ref(env)?.cast_value_int(env, hist, v),
1267 t => match t.first_prim(env) {
1268 None => bail!("empty or non primitive cast"),
1269 Some(t) => Ok(v
1270 .clone()
1271 .cast(t)
1272 .ok_or_else(|| anyhow!("can't cast {v} to {t}"))?),
1273 },
1274 }
1275 }
1276
1277 pub fn cast_value<R: Rt, E: UserEvent>(&self, env: &Env<R, E>, v: Value) -> Value {
1278 thread_local! {
1279 static HIST: RefCell<FxHashSet<usize>> = RefCell::new(HashSet::default());
1280 }
1281 HIST.with_borrow_mut(|hist| {
1282 hist.clear();
1283 match self.cast_value_int(env, hist, v) {
1284 Ok(v) => v,
1285 Err(e) => Value::Error(e.to_string().into()),
1286 }
1287 })
1288 }
1289
1290 fn is_a_int<R: Rt, E: UserEvent>(
1291 &self,
1292 env: &Env<R, E>,
1293 hist: &mut FxHashSet<usize>,
1294 v: &Value,
1295 ) -> bool {
1296 match self {
1297 Type::Ref { .. } => match self.lookup_ref(env) {
1298 Err(_) => false,
1299 Ok(t) => {
1300 let t_addr = (t as *const Type).addr();
1301 !hist.contains(&t_addr) && {
1302 hist.insert(t_addr);
1303 t.is_a_int(env, hist, v)
1304 }
1305 }
1306 },
1307 Type::Primitive(t) => t.contains(Typ::get(&v)),
1308 Type::Any => true,
1309 Type::Array(et) => match v {
1310 Value::Array(a) => a.iter().all(|v| et.is_a_int(env, hist, v)),
1311 _ => false,
1312 },
1313 Type::ByRef(_) => matches!(v, Value::U64(_) | Value::V64(_)),
1314 Type::Tuple(ts) => match v {
1315 Value::Array(elts) => {
1316 elts.len() == ts.len()
1317 && ts
1318 .iter()
1319 .zip(elts.iter())
1320 .all(|(t, v)| t.is_a_int(env, hist, v))
1321 }
1322 _ => false,
1323 },
1324 Type::Struct(ts) => match v {
1325 Value::Array(elts) => {
1326 elts.len() == ts.len()
1327 && ts.iter().zip(elts.iter()).all(|((n, t), v)| match v {
1328 Value::Array(a) if a.len() == 2 => match &a[..] {
1329 [Value::String(key), v] => {
1330 n == key && t.is_a_int(env, hist, v)
1331 }
1332 _ => false,
1333 },
1334 _ => false,
1335 })
1336 }
1337 _ => false,
1338 },
1339 Type::Variant(tag, ts) if ts.len() == 0 => match &v {
1340 Value::String(s) => s == tag,
1341 _ => false,
1342 },
1343 Type::Variant(tag, ts) => match &v {
1344 Value::Array(elts) => {
1345 ts.len() + 1 == elts.len()
1346 && match &elts[0] {
1347 Value::String(s) => s == tag,
1348 _ => false,
1349 }
1350 && ts
1351 .iter()
1352 .zip(elts[1..].iter())
1353 .all(|(t, v)| t.is_a_int(env, hist, v))
1354 }
1355 _ => false,
1356 },
1357 Type::TVar(tv) => match &*tv.read().typ.read() {
1358 None => true,
1359 Some(t) => t.is_a_int(env, hist, v),
1360 },
1361 Type::Fn(_) => match v {
1362 Value::U64(_) => true,
1363 _ => false,
1364 },
1365 Type::Bottom => true,
1366 Type::Set(ts) => ts.iter().any(|t| t.is_a_int(env, hist, v)),
1367 }
1368 }
1369
1370 pub fn is_a<R: Rt, E: UserEvent>(&self, env: &Env<R, E>, v: &Value) -> bool {
1372 thread_local! {
1373 static HIST: RefCell<FxHashSet<usize>> = RefCell::new(HashSet::default());
1374 }
1375 HIST.with_borrow_mut(|hist| {
1376 hist.clear();
1377 self.is_a_int(env, hist, v)
1378 })
1379 }
1380
1381 pub fn is_bot(&self) -> bool {
1382 match self {
1383 Type::Bottom => true,
1384 Type::Any
1385 | Type::TVar(_)
1386 | Type::Primitive(_)
1387 | Type::Ref { .. }
1388 | Type::Fn(_)
1389 | Type::Array(_)
1390 | Type::ByRef(_)
1391 | Type::Tuple(_)
1392 | Type::Struct(_)
1393 | Type::Variant(_, _)
1394 | Type::Set(_) => false,
1395 }
1396 }
1397
1398 pub fn with_deref<R, F: FnOnce(Option<&Self>) -> R>(&self, f: F) -> R {
1399 match self {
1400 Self::Bottom
1401 | Self::Any
1402 | Self::Primitive(_)
1403 | Self::Fn(_)
1404 | Self::Set(_)
1405 | Self::Array(_)
1406 | Self::ByRef(_)
1407 | Self::Tuple(_)
1408 | Self::Struct(_)
1409 | Self::Variant(_, _)
1410 | Self::Ref { .. } => f(Some(self)),
1411 Self::TVar(tv) => f(tv.read().typ.read().as_ref()),
1412 }
1413 }
1414
1415 pub(crate) fn flatten_set(set: impl IntoIterator<Item = Self>) -> Self {
1416 let init: Box<dyn Iterator<Item = Self>> = Box::new(set.into_iter());
1417 let mut iters: SmallVec<[Box<dyn Iterator<Item = Self>>; 16]> = smallvec![init];
1418 let mut acc: SmallVec<[Self; 16]> = smallvec![];
1419 loop {
1420 match iters.last_mut() {
1421 None => break,
1422 Some(iter) => match iter.next() {
1423 None => {
1424 iters.pop();
1425 }
1426 Some(Type::Set(s)) => {
1427 let v: SmallVec<[Self; 16]> =
1428 s.iter().map(|t| t.clone()).collect();
1429 iters.push(Box::new(v.into_iter()))
1430 }
1431 Some(Type::Any) => return Type::Any,
1432 Some(t) => {
1433 acc.push(t);
1434 let mut i = 0;
1435 let mut j;
1436 while i < acc.len() {
1437 j = i + 1;
1438 while j < acc.len() {
1439 if let Some(t) = acc[i].merge(&acc[j]) {
1440 acc[i] = t;
1441 acc.remove(j);
1442 } else {
1443 j += 1;
1444 }
1445 }
1446 i += 1;
1447 }
1448 }
1449 },
1450 }
1451 }
1452 acc.sort();
1453 match &*acc {
1454 [] => Type::Primitive(BitFlags::empty()),
1455 [t] => t.clone(),
1456 _ => Type::Set(Arc::from_iter(acc)),
1457 }
1458 }
1459
1460 pub(crate) fn normalize(&self) -> Self {
1461 match self {
1462 Type::Bottom | Type::Any | Type::Primitive(_) => self.clone(),
1463 Type::Ref { scope, name, params } => {
1464 let params = Arc::from_iter(params.iter().map(|t| t.normalize()));
1465 Type::Ref { scope: scope.clone(), name: name.clone(), params }
1466 }
1467 Type::TVar(tv) => Type::TVar(tv.normalize()),
1468 Type::Set(s) => Self::flatten_set(s.iter().map(|t| t.normalize())),
1469 Type::Array(t) => Type::Array(Arc::new(t.normalize())),
1470 Type::ByRef(t) => Type::ByRef(Arc::new(t.normalize())),
1471 Type::Tuple(t) => {
1472 Type::Tuple(Arc::from_iter(t.iter().map(|t| t.normalize())))
1473 }
1474 Type::Struct(t) => Type::Struct(Arc::from_iter(
1475 t.iter().map(|(n, t)| (n.clone(), t.normalize())),
1476 )),
1477 Type::Variant(tag, t) => Type::Variant(
1478 tag.clone(),
1479 Arc::from_iter(t.iter().map(|t| t.normalize())),
1480 ),
1481 Type::Fn(ft) => Type::Fn(Arc::new(ft.normalize())),
1482 }
1483 }
1484
1485 fn merge(&self, t: &Self) -> Option<Self> {
1486 match (self, t) {
1487 (
1488 Type::Ref { scope: s0, name: r0, params: a0 },
1489 Type::Ref { scope: s1, name: r1, params: a1 },
1490 ) => {
1491 if s0 == s1 && r0 == r1 && a0 == a1 {
1492 Some(Type::Ref {
1493 scope: s0.clone(),
1494 name: r0.clone(),
1495 params: a0.clone(),
1496 })
1497 } else {
1498 None
1499 }
1500 }
1501 (Type::Ref { .. }, _) | (_, Type::Ref { .. }) => None,
1502 (Type::Bottom, t) | (t, Type::Bottom) => Some(t.clone()),
1503 (Type::Any, _) | (_, Type::Any) => Some(Type::Any),
1504 (Type::Primitive(p), t) | (t, Type::Primitive(p)) if p.is_empty() => {
1505 Some(t.clone())
1506 }
1507 (Type::Primitive(s0), Type::Primitive(s1)) => {
1508 let mut s = *s0;
1509 s.insert(*s1);
1510 Some(Type::Primitive(s))
1511 }
1512 (Type::Fn(f0), Type::Fn(f1)) => {
1513 if f0 == f1 {
1514 Some(Type::Fn(f0.clone()))
1515 } else {
1516 None
1517 }
1518 }
1519 (Type::Array(t0), Type::Array(t1)) => {
1520 let t0f = match &**t0 {
1521 Type::Set(et) => Self::flatten_set(et.iter().cloned()),
1522 t => t.clone(),
1523 };
1524 let t1f = match &**t1 {
1525 Type::Set(et) => Self::flatten_set(et.iter().cloned()),
1526 t => t.clone(),
1527 };
1528 if t0f == t1f {
1529 Some(Type::Array(t0.clone()))
1530 } else {
1531 None
1532 }
1533 }
1534 (Type::ByRef(t0), Type::ByRef(t1)) => {
1535 t0.merge(t1).map(|t| Type::ByRef(Arc::new(t)))
1536 }
1537 (Type::ByRef(_), _) | (_, Type::ByRef(_)) => None,
1538 (Type::Array(_), _) | (_, Type::Array(_)) => None,
1539 (Type::Set(s0), Type::Set(s1)) => {
1540 Some(Self::flatten_set(s0.iter().cloned().chain(s1.iter().cloned())))
1541 }
1542 (Type::Set(s), Type::Primitive(p)) | (Type::Primitive(p), Type::Set(s))
1543 if p.is_empty() =>
1544 {
1545 Some(Type::Set(s.clone()))
1546 }
1547 (Type::Set(s), t) | (t, Type::Set(s)) => {
1548 Some(Self::flatten_set(s.iter().cloned().chain(iter::once(t.clone()))))
1549 }
1550 (Type::Tuple(t0), Type::Tuple(t1)) => {
1551 if t0.len() == t1.len() {
1552 let t = t0
1553 .iter()
1554 .zip(t1.iter())
1555 .map(|(t0, t1)| t0.merge(t1))
1556 .collect::<Option<SmallVec<[Type; 8]>>>()?;
1557 Some(Type::Tuple(Arc::from_iter(t)))
1558 } else {
1559 None
1560 }
1561 }
1562 (Type::Variant(tag0, t0), Type::Variant(tag1, t1)) => {
1563 if tag0 == tag1 && t0.len() == t1.len() {
1564 let t = t0
1565 .iter()
1566 .zip(t1.iter())
1567 .map(|(t0, t1)| t0.merge(t1))
1568 .collect::<Option<SmallVec<[Type; 8]>>>()?;
1569 Some(Type::Variant(tag0.clone(), Arc::from_iter(t)))
1570 } else {
1571 None
1572 }
1573 }
1574 (Type::Struct(t0), Type::Struct(t1)) => {
1575 if t0.len() == t1.len() {
1576 let t = t0
1577 .iter()
1578 .zip(t1.iter())
1579 .map(|((n0, t0), (n1, t1))| {
1580 if n0 != n1 {
1581 None
1582 } else {
1583 t0.merge(t1).map(|t| (n0.clone(), t))
1584 }
1585 })
1586 .collect::<Option<SmallVec<[(ArcStr, Type); 8]>>>()?;
1587 Some(Type::Struct(Arc::from_iter(t)))
1588 } else {
1589 None
1590 }
1591 }
1592 (Type::TVar(tv0), Type::TVar(tv1)) if tv0.name == tv1.name && tv0 == tv1 => {
1593 Some(Type::TVar(tv0.clone()))
1594 }
1595 (Type::TVar(tv), t) => {
1596 tv.read().typ.read().as_ref().and_then(|tv| tv.merge(t))
1597 }
1598 (t, Type::TVar(tv)) => {
1599 tv.read().typ.read().as_ref().and_then(|tv| t.merge(tv))
1600 }
1601 (Type::Tuple(_), _)
1602 | (_, Type::Tuple(_))
1603 | (Type::Struct(_), _)
1604 | (_, Type::Struct(_))
1605 | (Type::Variant(_, _), _)
1606 | (_, Type::Variant(_, _))
1607 | (_, Type::Fn(_))
1608 | (Type::Fn(_), _) => None,
1609 }
1610 }
1611
1612 pub fn scope_refs(&self, scope: &ModPath) -> Type {
1613 match self {
1614 Type::Bottom => Type::Bottom,
1615 Type::Any => Type::Any,
1616 Type::Primitive(s) => Type::Primitive(*s),
1617 Type::Array(t0) => Type::Array(Arc::new(t0.scope_refs(scope))),
1618 Type::ByRef(t) => Type::ByRef(Arc::new(t.scope_refs(scope))),
1619 Type::Tuple(ts) => {
1620 let i = ts.iter().map(|t| t.scope_refs(scope));
1621 Type::Tuple(Arc::from_iter(i))
1622 }
1623 Type::Variant(tag, ts) => {
1624 let i = ts.iter().map(|t| t.scope_refs(scope));
1625 Type::Variant(tag.clone(), Arc::from_iter(i))
1626 }
1627 Type::Struct(ts) => {
1628 let i = ts.iter().map(|(n, t)| (n.clone(), t.scope_refs(scope)));
1629 Type::Struct(Arc::from_iter(i))
1630 }
1631 Type::TVar(tv) => match tv.read().typ.read().as_ref() {
1632 None => Type::TVar(TVar::empty_named(tv.name.clone())),
1633 Some(typ) => {
1634 let typ = typ.scope_refs(scope);
1635 Type::TVar(TVar::named(tv.name.clone(), typ))
1636 }
1637 },
1638 Type::Ref { scope: _, name, params } => {
1639 let params = Arc::from_iter(params.iter().map(|t| t.scope_refs(scope)));
1640 Type::Ref { scope: scope.clone(), name: name.clone(), params }
1641 }
1642 Type::Set(ts) => {
1643 Type::Set(Arc::from_iter(ts.iter().map(|t| t.scope_refs(scope))))
1644 }
1645 Type::Fn(f) => {
1646 let vargs = f.vargs.as_ref().map(|t| t.scope_refs(scope));
1647 let rtype = f.rtype.scope_refs(scope);
1648 let args = Arc::from_iter(f.args.iter().map(|a| FnArgType {
1649 label: a.label.clone(),
1650 typ: a.typ.scope_refs(scope),
1651 }));
1652 let mut cres: SmallVec<[(TVar, Type); 4]> = smallvec![];
1653 for (tv, tc) in f.constraints.read().iter() {
1654 let tv = tv.scope_refs(scope);
1655 let tc = tc.scope_refs(scope);
1656 cres.push((tv, tc));
1657 }
1658 Type::Fn(Arc::new(FnType {
1659 args,
1660 rtype,
1661 constraints: Arc::new(RwLock::new(cres.into_iter().collect())),
1662 vargs,
1663 }))
1664 }
1665 }
1666 }
1667}
1668
1669impl fmt::Display for Type {
1670 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1671 match self {
1672 Self::Bottom => write!(f, "_"),
1673 Self::Any => write!(f, "Any"),
1674 Self::Ref { scope: _, name, params } => {
1675 write!(f, "{name}")?;
1676 if !params.is_empty() {
1677 write!(f, "<")?;
1678 for (i, t) in params.iter().enumerate() {
1679 write!(f, "{t}")?;
1680 if i < params.len() - 1 {
1681 write!(f, ", ")?;
1682 }
1683 }
1684 write!(f, ">")?;
1685 }
1686 Ok(())
1687 }
1688 Self::TVar(tv) => write!(f, "{tv}"),
1689 Self::Fn(t) => write!(f, "{t}"),
1690 Self::Array(t) => write!(f, "Array<{t}>"),
1691 Self::ByRef(t) => write!(f, "&{t}"),
1692 Self::Tuple(ts) => {
1693 write!(f, "(")?;
1694 for (i, t) in ts.iter().enumerate() {
1695 write!(f, "{t}")?;
1696 if i < ts.len() - 1 {
1697 write!(f, ", ")?;
1698 }
1699 }
1700 write!(f, ")")
1701 }
1702 Self::Variant(tag, ts) if ts.len() == 0 => {
1703 write!(f, "`{tag}")
1704 }
1705 Self::Variant(tag, ts) => {
1706 write!(f, "`{tag}(")?;
1707 for (i, t) in ts.iter().enumerate() {
1708 write!(f, "{t}")?;
1709 if i < ts.len() - 1 {
1710 write!(f, ", ")?
1711 }
1712 }
1713 write!(f, ")")
1714 }
1715 Self::Struct(ts) => {
1716 write!(f, "{{")?;
1717 for (i, (n, t)) in ts.iter().enumerate() {
1718 write!(f, "{n}: {t}")?;
1719 if i < ts.len() - 1 {
1720 write!(f, ", ")?
1721 }
1722 }
1723 write!(f, "}}")
1724 }
1725 Self::Set(s) => {
1726 write!(f, "[")?;
1727 for (i, t) in s.iter().enumerate() {
1728 write!(f, "{t}")?;
1729 if i < s.len() - 1 {
1730 write!(f, ", ")?;
1731 }
1732 }
1733 write!(f, "]")
1734 }
1735 Self::Primitive(s) => {
1736 let replace = PRINT_FLAGS.get().contains(PrintFlag::ReplacePrims);
1737 if replace && *s == Typ::number() {
1738 write!(f, "Number")
1739 } else if replace && *s == Typ::float() {
1740 write!(f, "Float")
1741 } else if replace && *s == Typ::real() {
1742 write!(f, "Real")
1743 } else if replace && *s == Typ::integer() {
1744 write!(f, "Int")
1745 } else if replace && *s == Typ::unsigned_integer() {
1746 write!(f, "Uint")
1747 } else if replace && *s == Typ::signed_integer() {
1748 write!(f, "Sint")
1749 } else if s.len() == 0 {
1750 write!(f, "[]")
1751 } else if s.len() == 1 {
1752 write!(f, "{}", s.iter().next().unwrap())
1753 } else {
1754 let mut s = *s;
1755 macro_rules! builtin {
1756 ($set:expr, $name:literal) => {
1757 if replace && s.contains($set) {
1758 s.remove($set);
1759 write!(f, $name)?;
1760 if !s.is_empty() {
1761 write!(f, ", ")?
1762 }
1763 }
1764 };
1765 }
1766 write!(f, "[")?;
1767 builtin!(Typ::number(), "Number");
1768 builtin!(Typ::real(), "Real");
1769 builtin!(Typ::float(), "Float");
1770 builtin!(Typ::integer(), "Int");
1771 builtin!(Typ::unsigned_integer(), "Uint");
1772 builtin!(Typ::signed_integer(), "Sint");
1773 for (i, t) in s.iter().enumerate() {
1774 write!(f, "{t}")?;
1775 if i < s.len() - 1 {
1776 write!(f, ", ")?;
1777 }
1778 }
1779 write!(f, "]")
1780 }
1781 }
1782 }
1783 }
1784}