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