graphix_compiler/typ/
mod.rs

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