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