graphix_compiler/typ/
mod.rs

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