graphix_compiler/typ/
mod.rs

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