fix: Type::{And, Or}(Set<Type>)

This commit is contained in:
Shunsuke Shibayama 2024-09-14 21:20:05 +09:00
parent 82bc710827
commit b0c31370c5
14 changed files with 661 additions and 466 deletions

View file

@ -42,24 +42,30 @@ fn comp_item_kind(t: &Type, muty: Mutability) -> CompletionItemKind {
Type::Subr(_) | Type::Quantified(_) => CompletionItemKind::FUNCTION, Type::Subr(_) | Type::Quantified(_) => CompletionItemKind::FUNCTION,
Type::ClassType => CompletionItemKind::CLASS, Type::ClassType => CompletionItemKind::CLASS,
Type::TraitType => CompletionItemKind::INTERFACE, Type::TraitType => CompletionItemKind::INTERFACE,
Type::Or(l, r) => { Type::Or(tys) => {
let l = comp_item_kind(l, muty); let fst = comp_item_kind(tys.iter().next().unwrap(), muty);
let r = comp_item_kind(r, muty); if tys
if l == r { .iter()
l .map(|t| comp_item_kind(t, muty))
.all(|k| k == fst)
{
fst
} else if muty.is_const() { } else if muty.is_const() {
CompletionItemKind::CONSTANT CompletionItemKind::CONSTANT
} else { } else {
CompletionItemKind::VARIABLE CompletionItemKind::VARIABLE
} }
} }
Type::And(l, r) => { Type::And(tys) => {
let l = comp_item_kind(l, muty); for k in tys.iter().map(|t| comp_item_kind(t, muty)) {
let r = comp_item_kind(r, muty); if k != CompletionItemKind::VARIABLE {
if l == CompletionItemKind::VARIABLE { return k;
r }
}
if muty.is_const() {
CompletionItemKind::CONSTANT
} else { } else {
l CompletionItemKind::VARIABLE
} }
} }
Type::Refinement(r) => comp_item_kind(&r.t, muty), Type::Refinement(r) => comp_item_kind(&r.t, muty),

View file

@ -382,6 +382,20 @@ impl<T: Hash + Eq + Clone> Set<T> {
self.insert(other); self.insert(other);
self self
} }
/// ```
/// # use erg_common::set;
/// assert_eq!(set!{1, 2}.product(&set!{3, 4}), set!{(&1, &3), (&1, &4), (&2, &3), (&2, &4)});
/// ```
pub fn product<'l, 'r, U: Hash + Eq>(&'l self, other: &'r Set<U>) -> Set<(&'l T, &'r U)> {
let mut res = set! {};
for x in self.iter() {
for y in other.iter() {
res.insert((x, y));
}
}
res
}
} }
impl<T: Hash + Ord> Set<T> { impl<T: Hash + Ord> Set<T> {

View file

@ -1407,6 +1407,8 @@ impl<T: Immutable + ?Sized> Immutable for &T {}
impl<T: Immutable> Immutable for Option<T> {} impl<T: Immutable> Immutable for Option<T> {}
impl<T: Immutable> Immutable for Vec<T> {} impl<T: Immutable> Immutable for Vec<T> {}
impl<T: Immutable> Immutable for [T] {} impl<T: Immutable> Immutable for [T] {}
impl<T: Immutable, U: Immutable> Immutable for (T, U) {}
impl<T: Immutable, U: Immutable, V: Immutable> Immutable for (T, U, V) {}
impl<T: Immutable + ?Sized> Immutable for Box<T> {} impl<T: Immutable + ?Sized> Immutable for Box<T> {}
impl<T: Immutable + ?Sized> Immutable for std::rc::Rc<T> {} impl<T: Immutable + ?Sized> Immutable for std::rc::Rc<T> {}
impl<T: Immutable + ?Sized> Immutable for std::sync::Arc<T> {} impl<T: Immutable + ?Sized> Immutable for std::sync::Arc<T> {}

View file

@ -18,6 +18,16 @@ impl<T: fmt::Display, E: fmt::Display> fmt::Display for Triple<T, E> {
} }
impl<T, E> Triple<T, E> { impl<T, E> Triple<T, E> {
pub const fn is_ok(&self) -> bool {
matches!(self, Triple::Ok(_))
}
pub const fn is_err(&self) -> bool {
matches!(self, Triple::Err(_))
}
pub const fn is_none(&self) -> bool {
matches!(self, Triple::None)
}
pub fn none_then(self, err: E) -> Result<T, E> { pub fn none_then(self, err: E) -> Result<T, E> {
match self { match self {
Triple::None => Err(err), Triple::None => Err(err),

View file

@ -754,9 +754,7 @@ impl Context {
self.structural_supertype_of(&l, rhs) self.structural_supertype_of(&l, rhs)
} }
// {1, 2, 3} :> {1} or {2, 3} == true // {1, 2, 3} :> {1} or {2, 3} == true
(Refinement(_refine), Or(l, r)) => { (Refinement(_refine), Or(tys)) => tys.iter().all(|ty| self.supertype_of(lhs, ty)),
self.supertype_of(lhs, l) && self.supertype_of(lhs, r)
}
// ({I: Int | True} :> Int) == true // ({I: Int | True} :> Int) == true
// {N: Nat | ...} :> Int) == false // {N: Nat | ...} :> Int) == false
// ({I: Int | I >= 0} :> Int) == false // ({I: Int | I >= 0} :> Int) == false
@ -808,41 +806,20 @@ impl Context {
self.sub_unify(&inst, l, &(), None).is_ok() self.sub_unify(&inst, l, &(), None).is_ok()
} }
// Int or Str :> Str or Int == (Int :> Str && Str :> Int) || (Int :> Int && Str :> Str) == true // Int or Str :> Str or Int == (Int :> Str && Str :> Int) || (Int :> Int && Str :> Str) == true
(Or(l_1, l_2), Or(r_1, r_2)) => { // Int or Str or NoneType :> Str or Int
if l_1.is_union_type() && self.supertype_of(l_1, rhs) { (Or(l), Or(r)) => r.iter().all(|r| l.iter().any(|l| self.supertype_of(l, r))),
return true;
}
if l_2.is_union_type() && self.supertype_of(l_2, rhs) {
return true;
}
(self.supertype_of(l_1, r_1) && self.supertype_of(l_2, r_2))
|| (self.supertype_of(l_1, r_2) && self.supertype_of(l_2, r_1))
}
// not Nat :> not Int == true // not Nat :> not Int == true
(Not(l), Not(r)) => self.subtype_of(l, r), (Not(l), Not(r)) => self.subtype_of(l, r),
// (Int or Str) :> Nat == Int :> Nat || Str :> Nat == true // (Int or Str) :> Nat == Int :> Nat || Str :> Nat == true
// (Num or Show) :> Show == Num :> Show || Show :> Num == true // (Num or Show) :> Show == Num :> Show || Show :> Num == true
(Or(l_or, r_or), rhs) => self.supertype_of(l_or, rhs) || self.supertype_of(r_or, rhs), (Or(ors), rhs) => ors.iter().any(|or| self.supertype_of(or, rhs)),
// Int :> (Nat or Str) == Int :> Nat && Int :> Str == false // Int :> (Nat or Str) == Int :> Nat && Int :> Str == false
(lhs, Or(l_or, r_or)) => self.supertype_of(lhs, l_or) && self.supertype_of(lhs, r_or), (lhs, Or(ors)) => ors.iter().all(|or| self.supertype_of(lhs, or)),
(And(l_1, l_2), And(r_1, r_2)) => { (And(l), And(r)) => r.iter().any(|r| l.iter().all(|l| self.supertype_of(l, r))),
if l_1.is_intersection_type() && self.supertype_of(l_1, rhs) {
return true;
}
if l_2.is_intersection_type() && self.supertype_of(l_2, rhs) {
return true;
}
(self.supertype_of(l_1, r_1) && self.supertype_of(l_2, r_2))
|| (self.supertype_of(l_1, r_2) && self.supertype_of(l_2, r_1))
}
// (Num and Show) :> Show == false // (Num and Show) :> Show == false
(And(l_and, r_and), rhs) => { (And(ands), rhs) => ands.iter().all(|and| self.supertype_of(and, rhs)),
self.supertype_of(l_and, rhs) && self.supertype_of(r_and, rhs)
}
// Show :> (Num and Show) == true // Show :> (Num and Show) == true
(lhs, And(l_and, r_and)) => { (lhs, And(ands)) => ands.iter().any(|and| self.supertype_of(lhs, and)),
self.supertype_of(lhs, l_and) || self.supertype_of(lhs, r_and)
}
// Not(Eq) :> Float == !(Eq :> Float) == true // Not(Eq) :> Float == !(Eq :> Float) == true
(Not(_), Obj) => false, (Not(_), Obj) => false,
(Not(l), rhs) => !self.supertype_of(l, rhs), (Not(l), rhs) => !self.supertype_of(l, rhs),
@ -914,18 +891,18 @@ impl Context {
Type::NamedTuple(fields) => fields.iter().cloned().collect(), Type::NamedTuple(fields) => fields.iter().cloned().collect(),
Type::Refinement(refine) => self.fields(&refine.t), Type::Refinement(refine) => self.fields(&refine.t),
Type::Structural(t) => self.fields(t), Type::Structural(t) => self.fields(t),
Type::Or(l, r) => { Type::Or(tys) => {
let l_fields = self.fields(l); let or_fields = tys.iter().map(|t| self.fields(t)).collect::<Set<_>>();
let r_fields = self.fields(r); let field_names = or_fields
let l_field_names = l_fields.keys().collect::<Set<_>>();
let r_field_names = r_fields.keys().collect::<Set<_>>();
let field_names = l_field_names.intersection(&r_field_names);
let mut fields = Dict::new();
for (name, l_t, r_t) in field_names
.iter() .iter()
.map(|&name| (name, &l_fields[name], &r_fields[name])) .flat_map(|fs| fs.keys())
.collect::<Set<_>>();
let mut fields = Dict::new();
for (name, tys) in field_names
.iter()
.map(|&name| (name, or_fields.iter().filter_map(|fields| fields.get(name))))
{ {
let union = self.union(l_t, r_t); let union = tys.fold(Never, |acc, ty| self.union(&acc, ty));
fields.insert(name.clone(), union); fields.insert(name.clone(), union);
} }
fields fields
@ -1408,6 +1385,8 @@ impl Context {
/// union({ .a = Int }, { .a = Str }) == { .a = Int or Str } /// union({ .a = Int }, { .a = Str }) == { .a = Int or Str }
/// union({ .a = Int }, { .a = Int; .b = Int }) == { .a = Int } or { .a = Int; .b = Int } # not to lost `b` information /// union({ .a = Int }, { .a = Int; .b = Int }) == { .a = Int } or { .a = Int; .b = Int } # not to lost `b` information
/// union((A and B) or C) == (A or C) and (B or C) /// union((A and B) or C) == (A or C) and (B or C)
/// union(Never, Int) == Int
/// union(Obj, Int) == Obj
/// ``` /// ```
pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type { pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type {
if lhs == rhs { if lhs == rhs {
@ -1470,10 +1449,9 @@ impl Context {
(Some(sub), Some(sup)) => bounded(sub.clone(), sup.clone()), (Some(sub), Some(sup)) => bounded(sub.clone(), sup.clone()),
_ => self.simple_union(lhs, rhs), _ => self.simple_union(lhs, rhs),
}, },
(other, or @ Or(_, _)) | (or @ Or(_, _), other) => self.union_add(or, other), (other, or @ Or(_)) | (or @ Or(_), other) => self.union_add(or, other),
// (A and B) or C ==> (A or C) and (B or C) // (A and B) or C ==> (A or C) and (B or C)
(and_t @ And(_, _), other) | (other, and_t @ And(_, _)) => { (And(ands), other) | (other, And(ands)) => {
let ands = and_t.ands();
let mut t = Type::Obj; let mut t = Type::Obj;
for branch in ands.iter() { for branch in ands.iter() {
let union = self.union(branch, other); let union = self.union(branch, other);
@ -1657,6 +1635,12 @@ impl Context {
/// Returns intersection of two types (`A and B`). /// Returns intersection of two types (`A and B`).
/// If `A` and `B` have a subtype relationship, it is equal to `min(A, B)`. /// If `A` and `B` have a subtype relationship, it is equal to `min(A, B)`.
/// ```erg
/// intersection(Nat, Int) == Nat
/// intersection(Int, Str) == Never
/// intersection(Obj, Int) == Int
/// intersection(Never, Int) == Never
/// ```
pub(crate) fn intersection(&self, lhs: &Type, rhs: &Type) -> Type { pub(crate) fn intersection(&self, lhs: &Type, rhs: &Type) -> Type {
if lhs == rhs { if lhs == rhs {
return lhs.clone(); return lhs.clone();
@ -1687,12 +1671,9 @@ impl Context {
(_, Not(r)) => self.diff(lhs, r), (_, Not(r)) => self.diff(lhs, r),
(Not(l), _) => self.diff(rhs, l), (Not(l), _) => self.diff(rhs, l),
// A and B and A == A and B // A and B and A == A and B
(other, and @ And(_, _)) | (and @ And(_, _), other) => { (other, and @ And(_)) | (and @ And(_), other) => self.intersection_add(and, other),
self.intersection_add(and, other)
}
// (A or B) and C == (A and C) or (B and C) // (A or B) and C == (A and C) or (B and C)
(or_t @ Or(_, _), other) | (other, or_t @ Or(_, _)) => { (Or(ors), other) | (other, Or(ors)) => {
let ors = or_t.ors();
if ors.iter().any(|t| t.has_unbound_var()) { if ors.iter().any(|t| t.has_unbound_var()) {
return self.simple_intersection(lhs, rhs); return self.simple_intersection(lhs, rhs);
} }
@ -1827,21 +1808,21 @@ impl Context {
fn narrow_type_by_pred(&self, t: Type, pred: &Predicate) -> Type { fn narrow_type_by_pred(&self, t: Type, pred: &Predicate) -> Type {
match (t, pred) { match (t, pred) {
( (
Type::Or(l, r), Type::Or(tys),
Predicate::NotEqual { Predicate::NotEqual {
rhs: TyParam::Value(v), rhs: TyParam::Value(v),
.. ..
}, },
) if v.is_none() => { ) if v.is_none() => {
let l = self.narrow_type_by_pred(*l, pred); let mut new_tys = Set::new();
let r = self.narrow_type_by_pred(*r, pred); for ty in tys {
if l.is_nonetype() { let ty = self.narrow_type_by_pred(ty, pred);
r if ty.is_nonelike() {
} else if r.is_nonetype() { continue;
l
} else {
or(l, r)
} }
new_tys.insert(ty);
}
Type::checked_or(new_tys)
} }
(Type::Refinement(refine), _) => { (Type::Refinement(refine), _) => {
let t = self.narrow_type_by_pred(*refine.t, pred); let t = self.narrow_type_by_pred(*refine.t, pred);
@ -1983,8 +1964,12 @@ impl Context {
guard.target.clone(), guard.target.clone(),
self.complement(&guard.to), self.complement(&guard.to),
)), )),
Or(l, r) => self.intersection(&self.complement(l), &self.complement(r)), Or(ors) => ors
And(l, r) => self.union(&self.complement(l), &self.complement(r)), .iter()
.fold(Obj, |l, r| self.intersection(&l, &self.complement(r))),
And(ands) => ands
.iter()
.fold(Never, |l, r| self.union(&l, &self.complement(r))),
other => not(other.clone()), other => not(other.clone()),
} }
} }
@ -2002,7 +1987,14 @@ impl Context {
match lhs { match lhs {
Type::FreeVar(fv) if fv.is_linked() => self.diff(&fv.crack(), rhs), Type::FreeVar(fv) if fv.is_linked() => self.diff(&fv.crack(), rhs),
// Type::And(l, r) => self.intersection(&self.diff(l, rhs), &self.diff(r, rhs)), // Type::And(l, r) => self.intersection(&self.diff(l, rhs), &self.diff(r, rhs)),
Type::Or(l, r) => self.union(&self.diff(l, rhs), &self.diff(r, rhs)), Type::Or(tys) => {
let mut new_tys = vec![];
for ty in tys {
let diff = self.diff(ty, rhs);
new_tys.push(diff);
}
new_tys.into_iter().fold(Never, |l, r| self.union(&l, &r))
}
_ => lhs.clone(), _ => lhs.clone(),
} }
} }

View file

@ -2285,44 +2285,42 @@ impl Context {
Err((t, errs)) Err((t, errs))
} }
} }
Type::And(l, r) => { Type::And(ands) => {
let l = match self.eval_t_params(*l, level, t_loc) { let mut new_ands = set! {};
Ok(l) => l, for and in ands.into_iter() {
Err((l, es)) => { match self.eval_t_params(and, level, t_loc) {
errs.extend(es); Ok(and) => {
l new_ands.insert(and);
} }
}; Err((and, es)) => {
let r = match self.eval_t_params(*r, level, t_loc) { new_ands.insert(and);
Ok(r) => r,
Err((r, es)) => {
errs.extend(es); errs.extend(es);
r
} }
}; }
let intersec = self.intersection(&l, &r); }
let intersec = new_ands
.into_iter()
.fold(Type::Obj, |l, r| self.intersection(&l, &r));
if errs.is_empty() { if errs.is_empty() {
Ok(intersec) Ok(intersec)
} else { } else {
Err((intersec, errs)) Err((intersec, errs))
} }
} }
Type::Or(l, r) => { Type::Or(ors) => {
let l = match self.eval_t_params(*l, level, t_loc) { let mut new_ors = set! {};
Ok(l) => l, for or in ors.into_iter() {
Err((l, es)) => { match self.eval_t_params(or, level, t_loc) {
errs.extend(es); Ok(or) => {
l new_ors.insert(or);
} }
}; Err((or, es)) => {
let r = match self.eval_t_params(*r, level, t_loc) { new_ors.insert(or);
Ok(r) => r,
Err((r, es)) => {
errs.extend(es); errs.extend(es);
r
} }
}; }
let union = self.union(&l, &r); }
let union = new_ors.into_iter().fold(Never, |l, r| self.union(&l, &r));
if errs.is_empty() { if errs.is_empty() {
Ok(union) Ok(union)
} else { } else {

View file

@ -289,17 +289,21 @@ impl Generalizer {
} }
proj_call(lhs, attr_name, args) proj_call(lhs, attr_name, args)
} }
And(l, r) => { And(ands) => {
let l = self.generalize_t(*l, uninit);
let r = self.generalize_t(*r, uninit);
// not `self.intersection` because types are generalized // not `self.intersection` because types are generalized
and(l, r) let ands = ands
.into_iter()
.map(|t| self.generalize_t(t, uninit))
.collect();
Type::checked_and(ands)
} }
Or(l, r) => { Or(ors) => {
let l = self.generalize_t(*l, uninit);
let r = self.generalize_t(*r, uninit);
// not `self.union` because types are generalized // not `self.union` because types are generalized
or(l, r) let ors = ors
.into_iter()
.map(|t| self.generalize_t(t, uninit))
.collect();
Type::checked_or(ors)
} }
Not(l) => not(self.generalize_t(*l, uninit)), Not(l) => not(self.generalize_t(*l, uninit)),
Structural(ty) => { Structural(ty) => {
@ -1045,15 +1049,23 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
let pred = self.deref_pred(*refine.pred)?; let pred = self.deref_pred(*refine.pred)?;
Ok(refinement(refine.var, t, pred)) Ok(refinement(refine.var, t, pred))
} }
And(l, r) => { And(ands) => {
let l = self.deref_tyvar(*l)?; let mut new_ands = vec![];
let r = self.deref_tyvar(*r)?; for t in ands.into_iter() {
Ok(self.ctx.intersection(&l, &r)) new_ands.push(self.deref_tyvar(t)?);
} }
Or(l, r) => { Ok(new_ands
let l = self.deref_tyvar(*l)?; .into_iter()
let r = self.deref_tyvar(*r)?; .fold(Type::Obj, |acc, t| self.ctx.intersection(&acc, &t)))
Ok(self.ctx.union(&l, &r)) }
Or(ors) => {
let mut new_ors = vec![];
for t in ors.into_iter() {
new_ors.push(self.deref_tyvar(t)?);
}
Ok(new_ors
.into_iter()
.fold(Type::Never, |acc, t| self.ctx.union(&acc, &t)))
} }
Not(ty) => { Not(ty) => {
let ty = self.deref_tyvar(*ty)?; let ty = self.deref_tyvar(*ty)?;
@ -1733,22 +1745,33 @@ impl Context {
/// ``` /// ```
pub(crate) fn squash_tyvar(&self, typ: Type) -> Type { pub(crate) fn squash_tyvar(&self, typ: Type) -> Type {
match typ { match typ {
Or(l, r) => { Or(tys) => {
let l = self.squash_tyvar(*l); let new_tys = tys
let r = self.squash_tyvar(*r); .into_iter()
.map(|t| self.squash_tyvar(t))
.collect::<Vec<_>>();
let mut union = Never;
// REVIEW: // REVIEW:
if l.is_unnamed_unbound_var() && r.is_unnamed_unbound_var() { if new_tys.iter().all(|t| t.is_unnamed_unbound_var()) {
match (self.subtype_of(&l, &r), self.subtype_of(&r, &l)) { for ty in new_tys.iter() {
if union == Never {
union = ty.clone();
continue;
}
match (self.subtype_of(&union, ty), self.subtype_of(&union, ty)) {
(true, true) | (true, false) => { (true, true) | (true, false) => {
let _ = self.sub_unify(&l, &r, &(), None); let _ = self.sub_unify(&union, ty, &(), None);
} }
(false, true) => { (false, true) => {
let _ = self.sub_unify(&r, &l, &(), None); let _ = self.sub_unify(ty, &union, &(), None);
} }
_ => {} _ => {}
} }
} }
self.union(&l, &r) }
new_tys
.into_iter()
.fold(Never, |acc, t| self.union(&acc, &t))
} }
FreeVar(ref fv) if fv.constraint_is_sandwiched() => { FreeVar(ref fv) if fv.constraint_is_sandwiched() => {
let (sub_t, super_t) = fv.get_subsup().unwrap(); let (sub_t, super_t) = fv.get_subsup().unwrap();

View file

@ -116,9 +116,12 @@ impl Context {
return Some(hint); return Some(hint);
} }
} }
(Type::And(l, r), found) => { (Type::And(tys), found) if tys.len() == 2 => {
let left = self.readable_type(l.as_ref().clone()); let mut iter = tys.iter();
let right = self.readable_type(r.as_ref().clone()); let l = iter.next().unwrap();
let r = iter.next().unwrap();
let left = self.readable_type(l.clone());
let right = self.readable_type(r.clone());
if self.supertype_of(l, found) { if self.supertype_of(l, found) {
let msg = switch_lang!( let msg = switch_lang!(
"japanese" => format!("{found}{left}のサブタイプですが、{right}のサブタイプではありません"), "japanese" => format!("{found}{left}のサブタイプですが、{right}のサブタイプではありません"),

View file

@ -1046,35 +1046,35 @@ impl Context {
} }
Type::Structural(t) => self.get_attr_info_from_attributive(t, ident, namespace), Type::Structural(t) => self.get_attr_info_from_attributive(t, ident, namespace),
// TODO: And // TODO: And
Type::Or(l, r) => { Type::Or(tys) => {
let l_info = self.get_attr_info_from_attributive(l, ident, namespace); let mut info = Triple::<VarInfo, _>::None;
let r_info = self.get_attr_info_from_attributive(r, ident, namespace); for ty in tys {
match (l_info, r_info) { match (
(Triple::Ok(l), Triple::Ok(r)) => { self.get_attr_info_from_attributive(ty, ident, namespace),
let res = self.union(&l.t, &r.t); &info,
let vis = if l.vis.is_public() && r.vis.is_public() { ) {
(Triple::Ok(vi), Triple::Ok(vi_)) => {
let res = self.union(&vi.t, &vi_.t);
let vis = if vi.vis.is_public() && vi_.vis.is_public() {
Visibility::DUMMY_PUBLIC Visibility::DUMMY_PUBLIC
} else { } else {
Visibility::DUMMY_PRIVATE Visibility::DUMMY_PRIVATE
}; };
let vi = VarInfo::new( let vi = VarInfo { t: res, vis, ..vi };
res, info = Triple::Ok(vi);
l.muty,
vis,
l.kind,
l.comptime_decos,
l.ctx,
l.py_name,
l.def_loc,
);
Triple::Ok(vi)
} }
(Triple::Ok(_), Triple::Err(e)) | (Triple::Err(e), Triple::Ok(_)) => { (Triple::Ok(vi), Triple::None) => {
Triple::Err(e) info = Triple::Ok(vi);
} }
(Triple::Err(e1), Triple::Err(_e2)) => Triple::Err(e1), (Triple::Err(err), _) => {
_ => Triple::None, info = Triple::Err(err);
break;
} }
(Triple::None, _) => {}
(_, Triple::Err(_)) => unreachable!(),
}
}
info
} }
_other => Triple::None, _other => Triple::None,
} }
@ -1952,7 +1952,7 @@ impl Context {
res res
} }
} }
Type::And(_, _) => { Type::And(_) => {
let instance = self.resolve_overload( let instance = self.resolve_overload(
obj, obj,
instance.clone(), instance.clone(),
@ -3012,32 +3012,30 @@ impl Context {
self.get_nominal_super_type_ctxs(&Type) self.get_nominal_super_type_ctxs(&Type)
} }
} }
Type::And(l, r) => { Type::And(tys) => {
match ( let mut acc = vec![];
self.get_nominal_super_type_ctxs(l), for ctxs in tys
self.get_nominal_super_type_ctxs(r), .iter()
) { .filter_map(|t| self.get_nominal_super_type_ctxs(t))
// TODO: sort
(Some(l), Some(r)) => Some([l, r].concat()),
(Some(l), None) => Some(l),
(None, Some(r)) => Some(r),
(None, None) => None,
}
}
// TODO
Type::Or(l, r) => match (l.as_ref(), r.as_ref()) {
(Type::FreeVar(l), Type::FreeVar(r))
if l.is_unbound_and_sandwiched() && r.is_unbound_and_sandwiched() =>
{ {
let (_lsub, lsup) = l.get_subsup().unwrap(); acc.extend(ctxs);
let (_rsub, rsup) = r.get_subsup().unwrap(); }
self.get_nominal_super_type_ctxs(&self.union(&lsup, &rsup)) if acc.is_empty() {
None
} else {
Some(acc)
}
}
Type::Or(tys) => {
let union = tys
.iter()
.fold(Never, |l, r| self.union(&l, &r.upper_bounded()));
if union.is_union_type() {
self.get_nominal_super_type_ctxs(&Obj)
} else {
self.get_nominal_super_type_ctxs(&union)
} }
(Type::Refinement(l), Type::Refinement(r)) if l.t == r.t => {
self.get_nominal_super_type_ctxs(&l.t)
} }
_ => self.get_nominal_type_ctx(&Obj).map(|ctx| vec![ctx]),
},
_ => self _ => self
.get_simple_nominal_super_type_ctxs(t) .get_simple_nominal_super_type_ctxs(t)
.map(|ctxs| ctxs.collect()), .map(|ctxs| ctxs.collect()),
@ -3231,7 +3229,7 @@ impl Context {
.unwrap_or(self) .unwrap_or(self)
.rec_local_get_mono_type("GenericNamedTuple"); .rec_local_get_mono_type("GenericNamedTuple");
} }
Type::Or(_l, _r) => { Type::Or(_) => {
if let Some(ctx) = self.get_nominal_type_ctx(&poly("Or", vec![])) { if let Some(ctx) = self.get_nominal_type_ctx(&poly("Or", vec![])) {
return Some(ctx); return Some(ctx);
} }
@ -3366,26 +3364,27 @@ impl Context {
match trait_ { match trait_ {
// And(Add, Sub) == intersection({Int <: Add(Int), Bool <: Add(Bool) ...}, {Int <: Sub(Int), ...}) // And(Add, Sub) == intersection({Int <: Add(Int), Bool <: Add(Bool) ...}, {Int <: Sub(Int), ...})
// == {Int <: Add(Int) and Sub(Int), ...} // == {Int <: Add(Int) and Sub(Int), ...}
Type::And(l, r) => { Type::And(tys) => {
let l_impls = self.get_trait_impls(l); let impls = tys
let l_base = Set::from_iter(l_impls.iter().map(|ti| &ti.sub_type)); .iter()
let r_impls = self.get_trait_impls(r); .flat_map(|ty| self.get_trait_impls(ty))
let r_base = Set::from_iter(r_impls.iter().map(|ti| &ti.sub_type)); .collect::<Set<_>>();
let bases = l_base.intersection(&r_base); let bases = impls.iter().map(|ti| &ti.sub_type);
let mut isec = set! {}; let mut isec = set! {};
for base in bases.into_iter() { for base in bases {
let lti = l_impls.iter().find(|ti| &ti.sub_type == base).unwrap(); let base_impls = impls.iter().filter(|ti| ti.sub_type == *base);
let rti = r_impls.iter().find(|ti| &ti.sub_type == base).unwrap(); let sup_trait =
let sup_trait = self.intersection(&lti.sup_trait, &rti.sup_trait); base_impls.fold(Obj, |l, r| self.intersection(&l, &r.sup_trait));
isec.insert(TraitImpl::new(lti.sub_type.clone(), sup_trait, None)); if sup_trait != Obj {
isec.insert(TraitImpl::new(base.clone(), sup_trait, None));
}
} }
isec isec
} }
Type::Or(l, r) => { Type::Or(tys) => {
let l_impls = self.get_trait_impls(l);
let r_impls = self.get_trait_impls(r);
// FIXME: // FIXME:
l_impls.union(&r_impls) tys.iter()
.fold(set! {}, |acc, ty| acc.union(&self.get_trait_impls(ty)))
} }
_ => self.get_simple_trait_impls(trait_), _ => self.get_simple_trait_impls(trait_),
} }
@ -3955,11 +3954,11 @@ impl Context {
pub fn is_class(&self, typ: &Type) -> bool { pub fn is_class(&self, typ: &Type) -> bool {
match typ { match typ {
Type::And(_l, _r) => false, Type::And(_) => false,
Type::Never => true, Type::Never => true,
Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.crack()), Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.crack()),
Type::FreeVar(_) => false, Type::FreeVar(_) => false,
Type::Or(l, r) => self.is_class(l) && self.is_class(r), Type::Or(tys) => tys.iter().all(|t| self.is_class(t)),
Type::Proj { lhs, rhs } => self Type::Proj { lhs, rhs } => self
.get_proj_candidates(lhs, rhs) .get_proj_candidates(lhs, rhs)
.iter() .iter()
@ -3982,7 +3981,8 @@ impl Context {
Type::Never => false, Type::Never => false,
Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.crack()), Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.crack()),
Type::FreeVar(_) => false, Type::FreeVar(_) => false,
Type::And(l, r) | Type::Or(l, r) => self.is_trait(l) && self.is_trait(r), Type::And(tys) => tys.iter().any(|t| self.is_trait(t)),
Type::Or(tys) => tys.iter().all(|t| self.is_trait(t)),
Type::Proj { lhs, rhs } => self Type::Proj { lhs, rhs } => self
.get_proj_candidates(lhs, rhs) .get_proj_candidates(lhs, rhs)
.iter() .iter()

View file

@ -953,15 +953,21 @@ impl Context {
let t = self.instantiate_t_inner(*t, tmp_tv_cache, loc)?; let t = self.instantiate_t_inner(*t, tmp_tv_cache, loc)?;
Ok(t.structuralize()) Ok(t.structuralize())
} }
And(l, r) => { And(tys) => {
let l = self.instantiate_t_inner(*l, tmp_tv_cache, loc)?; let mut new_tys = vec![];
let r = self.instantiate_t_inner(*r, tmp_tv_cache, loc)?; for ty in tys.iter().cloned() {
Ok(self.intersection(&l, &r)) new_tys.push(self.instantiate_t_inner(ty, tmp_tv_cache, loc)?);
} }
Or(l, r) => { Ok(new_tys
let l = self.instantiate_t_inner(*l, tmp_tv_cache, loc)?; .into_iter()
let r = self.instantiate_t_inner(*r, tmp_tv_cache, loc)?; .fold(Obj, |l, r| self.intersection(&l, &r)))
Ok(self.union(&l, &r)) }
Or(tys) => {
let mut new_tys = vec![];
for ty in tys.iter().cloned() {
new_tys.push(self.instantiate_t_inner(ty, tmp_tv_cache, loc)?);
}
Ok(new_tys.into_iter().fold(Never, |l, r| self.union(&l, &r)))
} }
Not(ty) => { Not(ty) => {
let ty = self.instantiate_t_inner(*ty, tmp_tv_cache, loc)?; let ty = self.instantiate_t_inner(*ty, tmp_tv_cache, loc)?;
@ -998,10 +1004,12 @@ impl Context {
let t = fv.crack().clone(); let t = fv.crack().clone();
self.instantiate(t, callee) self.instantiate(t, callee)
} }
And(lhs, rhs) => { And(tys) => {
let lhs = self.instantiate(*lhs, callee)?; let tys = tys
let rhs = self.instantiate(*rhs, callee)?; .into_iter()
Ok(lhs & rhs) .map(|t| self.instantiate(t, callee))
.collect::<TyCheckResult<Vec<_>>>()?;
Ok(tys.into_iter().fold(Obj, |l, r| l & r))
} }
Quantified(quant) => { Quantified(quant) => {
let mut tmp_tv_cache = TyVarCache::new(self.level, self); let mut tmp_tv_cache = TyVarCache::new(self.level, self);
@ -1028,8 +1036,9 @@ impl Context {
)?; )?;
} }
} }
Type::And(l, r) => { Type::And(tys) => {
if let Some(self_t) = l.self_t() { for ty in tys {
if let Some(self_t) = ty.self_t() {
self.sub_unify( self.sub_unify(
callee.ref_t(), callee.ref_t(),
self_t, self_t,
@ -1037,13 +1046,6 @@ impl Context {
Some(&Str::ever("self")), Some(&Str::ever("self")),
)?; )?;
} }
if let Some(self_t) = r.self_t() {
self.sub_unify(
callee.ref_t(),
self_t,
callee,
Some(&Str::ever("self")),
)?;
} }
} }
other => unreachable!("{other}"), other => unreachable!("{other}"),
@ -1066,10 +1068,12 @@ impl Context {
let t = fv.crack().clone(); let t = fv.crack().clone();
self.instantiate_dummy(t) self.instantiate_dummy(t)
} }
And(lhs, rhs) => { And(tys) => {
let lhs = self.instantiate_dummy(*lhs)?; let tys = tys
let rhs = self.instantiate_dummy(*rhs)?; .into_iter()
Ok(lhs & rhs) .map(|t| self.instantiate_dummy(t))
.collect::<TyCheckResult<Vec<_>>>()?;
Ok(tys.into_iter().fold(Obj, |l, r| l & r))
} }
Quantified(quant) => { Quantified(quant) => {
let mut tmp_tv_cache = TyVarCache::new(self.level, self); let mut tmp_tv_cache = TyVarCache::new(self.level, self);

View file

@ -155,17 +155,38 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
} }
Ok(()) Ok(())
} }
(Or(l, r), Or(l2, r2)) | (And(l, r), And(l2, r2)) => self (Or(l), Or(r)) | (And(l), And(r)) if l.len() == r.len() => {
.occur(l, l2) let l = l.to_vec();
.and(self.occur(r, r2)) let mut r = r.to_vec();
.or(self.occur(l, r2).and(self.occur(r, l2))), for _ in 0..r.len() {
(lhs, Or(l, r)) | (lhs, And(l, r)) => { if l.iter()
self.occur_inner(lhs, l)?; .zip(r.iter())
self.occur_inner(lhs, r) .all(|(l, r)| self.occur(l, r).is_ok())
{
return Ok(());
} }
(Or(l, r), rhs) | (And(l, r), rhs) => { r.rotate_left(1);
self.occur_inner(l, rhs)?; }
self.occur_inner(r, rhs) Err(TyCheckErrors::from(TyCheckError::subtyping_error(
self.ctx.cfg.input.clone(),
line!() as usize,
maybe_sub,
maybe_sup,
self.loc.loc(),
self.ctx.caused_by(),
)))
}
(lhs, Or(tys)) | (lhs, And(tys)) => {
for ty in tys.iter() {
self.occur(lhs, ty)?;
}
Ok(())
}
(Or(tys), rhs) | (And(tys), rhs) => {
for ty in tys.iter() {
self.occur(ty, rhs)?;
}
Ok(())
} }
_ => Ok(()), _ => Ok(()),
} }
@ -266,13 +287,17 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
} }
Ok(()) Ok(())
} }
(lhs, Or(l, r)) | (lhs, And(l, r)) => { (lhs, Or(tys)) | (lhs, And(tys)) => {
self.occur_inner(lhs, l)?; for ty in tys.iter() {
self.occur_inner(lhs, r) self.occur_inner(lhs, ty)?;
} }
(Or(l, r), rhs) | (And(l, r), rhs) => { Ok(())
self.occur_inner(l, rhs)?; }
self.occur_inner(r, rhs) (Or(tys), rhs) | (And(tys), rhs) => {
for ty in tys.iter() {
self.occur_inner(ty, rhs)?;
}
Ok(())
} }
_ => Ok(()), _ => Ok(()),
} }
@ -1186,35 +1211,42 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
// (Int or ?T) <: (?U or Int) // (Int or ?T) <: (?U or Int)
// OK: (Int <: Int); (?T <: ?U) // OK: (Int <: Int); (?T <: ?U)
// NG: (Int <: ?U); (?T <: Int) // NG: (Int <: ?U); (?T <: Int)
(Or(l1, r1), Or(l2, r2)) | (And(l1, r1), And(l2, r2)) => { (Or(ltys), Or(rtys)) | (And(ltys), And(rtys)) => {
if self.ctx.subtype_of(l1, l2) && self.ctx.subtype_of(r1, r2) { let lvars = ltys.to_vec();
let (l_sup, r_sup) = if !l1.is_unbound_var() let mut rvars = rtys.to_vec();
&& !r2.is_unbound_var() for _ in 0..rvars.len() {
&& self.ctx.subtype_of(l1, r2) if lvars
.iter()
.zip(rvars.iter())
.all(|(l, r)| self.ctx.subtype_of(l, r))
{ {
(r2, l2) for (l, r) in ltys.iter().zip(rtys.iter()) {
} else { self.sub_unify(l, r)?;
(l2, r2)
};
self.sub_unify(l1, l_sup)?;
self.sub_unify(r1, r_sup)?;
} else {
self.sub_unify(l1, r2)?;
self.sub_unify(r1, l2)?;
} }
break;
}
rvars.rotate_left(1);
}
return Err(TyCheckErrors::from(TyCheckError::type_mismatch_error(
self.ctx.cfg.input.clone(),
line!() as usize,
self.loc.loc(),
self.ctx.caused_by(),
self.param_name.as_ref().unwrap_or(&Str::ever("_")),
None,
maybe_sup,
maybe_sub,
self.ctx.get_candidates(maybe_sub),
self.ctx.get_simple_type_mismatch_hint(maybe_sup, maybe_sub),
)));
} }
// NG: Nat <: ?T or Int ==> Nat or Int (?T = Nat) // NG: Nat <: ?T or Int ==> Nat or Int (?T = Nat)
// OK: Nat <: ?T or Int ==> ?T or Int // OK: Nat <: ?T or Int ==> ?T or Int
(sub, Or(l, r)) (sub, Or(tys))
if l.is_unbound_var() if !sub.is_unbound_var()
&& !sub.is_unbound_var() && tys
&& !r.is_unbound_var() .iter()
&& self.ctx.subtype_of(sub, r) => {} .any(|ty| !ty.is_unbound_var() && self.ctx.subtype_of(sub, ty)) => {}
(sub, Or(l, r))
if r.is_unbound_var()
&& !sub.is_unbound_var()
&& !l.is_unbound_var()
&& self.ctx.subtype_of(sub, l) => {}
// e.g. Structural({ .method = (self: T) -> Int })/T // e.g. Structural({ .method = (self: T) -> Int })/T
(Structural(sub), FreeVar(sup_fv)) (Structural(sub), FreeVar(sup_fv))
if sup_fv.is_unbound() && sub.contains_tvar(sup_fv) => {} if sup_fv.is_unbound() && sub.contains_tvar(sup_fv) => {}
@ -1578,31 +1610,37 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
} }
} }
// (X or Y) <: Z is valid when X <: Z and Y <: Z // (X or Y) <: Z is valid when X <: Z and Y <: Z
(Or(l, r), _) => { (Or(tys), _) => {
self.sub_unify(l, maybe_sup)?; for ty in tys {
self.sub_unify(r, maybe_sup)?; self.sub_unify(ty, maybe_sup)?;
}
} }
// X <: (Y and Z) is valid when X <: Y and X <: Z // X <: (Y and Z) is valid when X <: Y and X <: Z
(_, And(l, r)) => { (_, And(tys)) => {
self.sub_unify(maybe_sub, l)?; for ty in tys {
self.sub_unify(maybe_sub, r)?; self.sub_unify(maybe_sub, ty)?;
}
} }
// (X and Y) <: Z is valid when X <: Z or Y <: Z // (X and Y) <: Z is valid when X <: Z or Y <: Z
(And(l, r), _) => { (And(tys), _) => {
if self.ctx.subtype_of(l, maybe_sup) { for ty in tys {
self.sub_unify(l, maybe_sup)?; if self.ctx.subtype_of(ty, maybe_sup) {
} else { self.sub_unify(ty, maybe_sup)?;
self.sub_unify(r, maybe_sup)?; break;
} }
} }
self.sub_unify(tys.iter().next().unwrap(), maybe_sup)?;
}
// X <: (Y or Z) is valid when X <: Y or X <: Z // X <: (Y or Z) is valid when X <: Y or X <: Z
(_, Or(l, r)) => { (_, Or(tys)) => {
if self.ctx.subtype_of(maybe_sub, l) { for ty in tys {
self.sub_unify(maybe_sub, l)?; if self.ctx.subtype_of(maybe_sub, ty) {
} else { self.sub_unify(maybe_sub, ty)?;
self.sub_unify(maybe_sub, r)?; break;
} }
} }
self.sub_unify(maybe_sub, tys.iter().next().unwrap())?;
}
(Ref(sub), Ref(sup)) => { (Ref(sub), Ref(sup)) => {
self.sub_unify(sub, sup)?; self.sub_unify(sub, sup)?;
} }
@ -1843,27 +1881,27 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
/// ``` /// ```
fn unify(&self, lhs: &Type, rhs: &Type) -> Option<Type> { fn unify(&self, lhs: &Type, rhs: &Type) -> Option<Type> {
match (lhs, rhs) { match (lhs, rhs) {
(Type::Or(l, r), other) | (other, Type::Or(l, r)) => { (Or(tys), other) | (other, Or(tys)) => {
if let Some(t) = self.unify(l, other) { for ty in tys {
return self.unify(&t, l); if let Some(t) = self.unify(ty, other) {
} else if let Some(t) = self.unify(r, other) { return self.unify(&t, ty);
return self.unify(&t, l); }
} }
return None; return None;
} }
(Type::FreeVar(fv), _) if fv.is_linked() => return self.unify(&fv.crack(), rhs), (FreeVar(fv), _) if fv.is_linked() => return self.unify(&fv.crack(), rhs),
(_, Type::FreeVar(fv)) if fv.is_linked() => return self.unify(lhs, &fv.crack()), (_, FreeVar(fv)) if fv.is_linked() => return self.unify(lhs, &fv.crack()),
// TODO: unify(?T, ?U) ? // TODO: unify(?T, ?U) ?
(Type::FreeVar(_), Type::FreeVar(_)) => {} (FreeVar(_), FreeVar(_)) => {}
(Type::FreeVar(fv), _) if fv.constraint_is_sandwiched() => { (FreeVar(fv), _) if fv.constraint_is_sandwiched() => {
let sub = fv.get_sub()?; let sub = fv.get_sub()?;
return self.unify(&sub, rhs); return self.unify(&sub, rhs);
} }
(_, Type::FreeVar(fv)) if fv.constraint_is_sandwiched() => { (_, FreeVar(fv)) if fv.constraint_is_sandwiched() => {
let sub = fv.get_sub()?; let sub = fv.get_sub()?;
return self.unify(lhs, &sub); return self.unify(lhs, &sub);
} }
(Type::Refinement(lhs), Type::Refinement(rhs)) => { (Refinement(lhs), Refinement(rhs)) => {
if let Some(_union) = self.unify(&lhs.t, &rhs.t) { if let Some(_union) = self.unify(&lhs.t, &rhs.t) {
return Some(self.ctx.union_refinement(lhs, rhs).into()); return Some(self.ctx.union_refinement(lhs, rhs).into());
} }

View file

@ -1502,9 +1502,10 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
} }
_ => {} _ => {}
}, },
Type::And(lhs, rhs) => { Type::And(tys) => {
self.push_guard(nth, kind, lhs); for ty in tys {
self.push_guard(nth, kind, rhs); self.push_guard(nth, kind, ty);
}
} }
_ => {} _ => {}
} }

View file

@ -593,35 +593,11 @@ pub fn refinement(var: Str, t: Type, pred: Predicate) -> Type {
} }
pub fn and(lhs: Type, rhs: Type) -> Type { pub fn and(lhs: Type, rhs: Type) -> Type {
match (lhs, rhs) { lhs & rhs
(Type::And(l, r), other) | (other, Type::And(l, r)) => {
if l.as_ref() == &other {
and(*r, other)
} else if r.as_ref() == &other {
and(*l, other)
} else {
Type::And(Box::new(Type::And(l, r)), Box::new(other))
}
}
(Type::Obj, other) | (other, Type::Obj) => other,
(lhs, rhs) => Type::And(Box::new(lhs), Box::new(rhs)),
}
} }
pub fn or(lhs: Type, rhs: Type) -> Type { pub fn or(lhs: Type, rhs: Type) -> Type {
match (lhs, rhs) { lhs | rhs
(Type::Or(l, r), other) | (other, Type::Or(l, r)) => {
if l.as_ref() == &other {
or(*r, other)
} else if r.as_ref() == &other {
or(*l, other)
} else {
Type::Or(Box::new(Type::Or(l, r)), Box::new(other))
}
}
(Type::Never, other) | (other, Type::Never) => other,
(lhs, rhs) => Type::Or(Box::new(lhs), Box::new(rhs)),
}
} }
pub fn ors(tys: impl IntoIterator<Item = Type>) -> Type { pub fn ors(tys: impl IntoIterator<Item = Type>) -> Type {

View file

@ -1410,8 +1410,8 @@ pub enum Type {
Refinement(RefinementType), Refinement(RefinementType),
// e.g. |T: Type| T -> T // e.g. |T: Type| T -> T
Quantified(Box<Type>), Quantified(Box<Type>),
And(Box<Type>, Box<Type>), And(Set<Type>),
Or(Box<Type>, Box<Type>), Or(Set<Type>),
Not(Box<Type>), Not(Box<Type>),
// NOTE: It was found that adding a new variant above `Poly` may cause a subtyping bug, // NOTE: It was found that adding a new variant above `Poly` may cause a subtyping bug,
// possibly related to enum internal numbering, but the cause is unknown. // possibly related to enum internal numbering, but the cause is unknown.
@ -1504,8 +1504,8 @@ impl PartialEq for Type {
(Self::NamedTuple(lhs), Self::NamedTuple(rhs)) => lhs == rhs, (Self::NamedTuple(lhs), Self::NamedTuple(rhs)) => lhs == rhs,
(Self::Refinement(l), Self::Refinement(r)) => l == r, (Self::Refinement(l), Self::Refinement(r)) => l == r,
(Self::Quantified(l), Self::Quantified(r)) => l == r, (Self::Quantified(l), Self::Quantified(r)) => l == r,
(Self::And(_, _), Self::And(_, _)) => self.ands().linear_eq(&other.ands()), (Self::And(l), Self::And(r)) => l.linear_eq(r),
(Self::Or(_, _), Self::Or(_, _)) => self.ors().linear_eq(&other.ors()), (Self::Or(l), Self::Or(r)) => l.linear_eq(r),
(Self::Not(l), Self::Not(r)) => l == r, (Self::Not(l), Self::Not(r)) => l == r,
( (
Self::Poly { Self::Poly {
@ -1659,20 +1659,28 @@ impl LimitedDisplay for Type {
write!(f, "|")?; write!(f, "|")?;
quantified.limited_fmt(f, limit - 1) quantified.limited_fmt(f, limit - 1)
} }
Self::And(lhs, rhs) => { Self::And(ands) => {
lhs.limited_fmt(f, limit - 1)?; for (i, ty) in ands.iter().enumerate() {
if i > 0 {
write!(f, " and ")?; write!(f, " and ")?;
rhs.limited_fmt(f, limit - 1) }
ty.limited_fmt(f, limit - 1)?;
}
Ok(())
}
Self::Or(ors) => {
for (i, ty) in ors.iter().enumerate() {
if i > 0 {
write!(f, " or ")?;
}
ty.limited_fmt(f, limit - 1)?;
}
Ok(())
} }
Self::Not(ty) => { Self::Not(ty) => {
write!(f, "not ")?; write!(f, "not ")?;
ty.limited_fmt(f, limit - 1) ty.limited_fmt(f, limit - 1)
} }
Self::Or(lhs, rhs) => {
lhs.limited_fmt(f, limit - 1)?;
write!(f, " or ")?;
rhs.limited_fmt(f, limit - 1)
}
Self::Poly { name, params } => { Self::Poly { name, params } => {
write!(f, "{name}(")?; write!(f, "{name}(")?;
if !DEBUG_MODE && self.is_module() { if !DEBUG_MODE && self.is_module() {
@ -1852,14 +1860,40 @@ impl From<Dict<Field, Type>> for Type {
impl BitAnd for Type { impl BitAnd for Type {
type Output = Self; type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output { fn bitand(self, rhs: Self) -> Self::Output {
Self::And(Box::new(self), Box::new(rhs)) match (self, rhs) {
(Self::And(l), Self::And(r)) => Self::And(l.union(&r)),
(Self::Obj, other) | (other, Self::Obj) => other,
(Self::Never, _) | (_, Self::Never) => Self::Never,
(Self::And(mut l), r) => {
l.insert(r);
Self::And(l)
}
(l, Self::And(mut r)) => {
r.insert(l);
Self::And(r)
}
(l, r) => Self::checked_and(set! {l, r}),
}
} }
} }
impl BitOr for Type { impl BitOr for Type {
type Output = Self; type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output { fn bitor(self, rhs: Self) -> Self::Output {
Self::Or(Box::new(self), Box::new(rhs)) match (self, rhs) {
(Self::Or(l), Self::Or(r)) => Self::Or(l.union(&r)),
(Self::Obj, _) | (_, Self::Obj) => Self::Obj,
(Self::Never, other) | (other, Self::Never) => other,
(Self::Or(mut l), r) => {
l.insert(r);
Self::Or(l)
}
(l, Self::Or(mut r)) => {
r.insert(l);
Self::Or(r)
}
(l, r) => Self::checked_or(set! {l, r}),
}
} }
} }
@ -1974,17 +2008,7 @@ impl HasLevel for Type {
.filter_map(|o| *o) .filter_map(|o| *o)
.min() .min()
} }
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => { Self::And(tys) | Self::Or(tys) => tys.iter().filter_map(|t| t.level()).min(),
let l = lhs
.level()
.unwrap_or(GENERIC_LEVEL)
.min(rhs.level().unwrap_or(GENERIC_LEVEL));
if l == GENERIC_LEVEL {
None
} else {
Some(l)
}
}
Self::Not(ty) => ty.level(), Self::Not(ty) => ty.level(),
Self::Record(attrs) => attrs.values().filter_map(|t| t.level()).min(), Self::Record(attrs) => attrs.values().filter_map(|t| t.level()).min(),
Self::NamedTuple(attrs) => attrs.iter().filter_map(|(_, t)| t.level()).min(), Self::NamedTuple(attrs) => attrs.iter().filter_map(|(_, t)| t.level()).min(),
@ -2065,9 +2089,10 @@ impl HasLevel for Type {
Self::Quantified(quant) => { Self::Quantified(quant) => {
quant.set_level(level); quant.set_level(level);
} }
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => { Self::And(tys) | Self::Or(tys) => {
lhs.set_level(level); for t in tys.iter() {
rhs.set_level(level); t.set_level(level);
}
} }
Self::Not(ty) => ty.set_level(level), Self::Not(ty) => ty.set_level(level),
Self::Record(attrs) => { Self::Record(attrs) => {
@ -2218,9 +2243,7 @@ impl StructuralEq for Type {
(Self::Guard(l), Self::Guard(r)) => l.structural_eq(r), (Self::Guard(l), Self::Guard(r)) => l.structural_eq(r),
// NG: (l.structural_eq(l2) && r.structural_eq(r2)) // NG: (l.structural_eq(l2) && r.structural_eq(r2))
// || (l.structural_eq(r2) && r.structural_eq(l2)) // || (l.structural_eq(r2) && r.structural_eq(l2))
(Self::And(_, _), Self::And(_, _)) => { (Self::And(self_ands), Self::And(other_ands)) => {
let self_ands = self.ands();
let other_ands = other.ands();
if self_ands.len() != other_ands.len() { if self_ands.len() != other_ands.len() {
return false; return false;
} }
@ -2234,9 +2257,7 @@ impl StructuralEq for Type {
} }
true true
} }
(Self::Or(_, _), Self::Or(_, _)) => { (Self::Or(self_ors), Self::Or(other_ors)) => {
let self_ors = self.ors();
let other_ors = other.ors();
if self_ors.len() != other_ors.len() { if self_ors.len() != other_ors.len() {
return false; return false;
} }
@ -2330,10 +2351,30 @@ impl Type {
} }
} }
pub fn checked_or(tys: Set<Type>) -> Self {
if tys.is_empty() {
panic!("tys is empty");
} else if tys.len() == 1 {
tys.into_iter().next().unwrap()
} else {
Self::Or(tys)
}
}
pub fn checked_and(tys: Set<Type>) -> Self {
if tys.is_empty() {
panic!("tys is empty");
} else if tys.len() == 1 {
tys.into_iter().next().unwrap()
} else {
Self::And(tys)
}
}
pub fn quantify(self) -> Self { pub fn quantify(self) -> Self {
debug_assert!(self.is_subr(), "{self} is not subr"); debug_assert!(self.is_subr(), "{self} is not subr");
match self { match self {
Self::And(lhs, rhs) => lhs.quantify() & rhs.quantify(), Self::And(tys) => Self::And(tys.into_iter().map(|t| t.quantify()).collect()),
other => Self::Quantified(Box::new(other)), other => Self::Quantified(Box::new(other)),
} }
} }
@ -2431,7 +2472,7 @@ impl Type {
Self::Quantified(t) => t.is_procedure(), Self::Quantified(t) => t.is_procedure(),
Self::Subr(subr) if subr.kind == SubrKind::Proc => true, Self::Subr(subr) if subr.kind == SubrKind::Proc => true,
Self::Refinement(refine) => refine.t.is_procedure(), Self::Refinement(refine) => refine.t.is_procedure(),
Self::And(lhs, rhs) => lhs.is_procedure() && rhs.is_procedure(), Self::And(tys) => tys.iter().any(|t| t.is_procedure()),
_ => false, _ => false,
} }
} }
@ -2449,6 +2490,7 @@ impl Type {
name.ends_with('!') name.ends_with('!')
} }
Self::Refinement(refine) => refine.t.is_mut_type(), Self::Refinement(refine) => refine.t.is_mut_type(),
Self::And(tys) => tys.iter().any(|t| t.is_mut_type()),
_ => false, _ => false,
} }
} }
@ -2467,6 +2509,7 @@ impl Type {
Self::Poly { name, params, .. } if &name[..] == "Tuple" => params.is_empty(), Self::Poly { name, params, .. } if &name[..] == "Tuple" => params.is_empty(),
Self::Refinement(refine) => refine.t.is_nonelike(), Self::Refinement(refine) => refine.t.is_nonelike(),
Self::Bounded { sup, .. } => sup.is_nonelike(), Self::Bounded { sup, .. } => sup.is_nonelike(),
Self::And(tys) => tys.iter().any(|t| t.is_nonelike()),
_ => false, _ => false,
} }
} }
@ -2516,7 +2559,7 @@ impl Type {
pub fn is_union_type(&self) -> bool { pub fn is_union_type(&self) -> bool {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_union_type(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_union_type(),
Self::Or(_, _) => true, Self::Or(_) => true,
Self::Refinement(refine) => refine.t.is_union_type(), Self::Refinement(refine) => refine.t.is_union_type(),
_ => false, _ => false,
} }
@ -2549,7 +2592,7 @@ impl Type {
pub fn is_intersection_type(&self) -> bool { pub fn is_intersection_type(&self) -> bool {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_intersection_type(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_intersection_type(),
Self::And(_, _) => true, Self::And(_) => true,
Self::Refinement(refine) => refine.t.is_intersection_type(), Self::Refinement(refine) => refine.t.is_intersection_type(),
_ => false, _ => false,
} }
@ -2563,11 +2606,11 @@ impl Type {
fv.do_avoiding_recursion(|| sub.union_size().max(sup.union_size())) fv.do_avoiding_recursion(|| sub.union_size().max(sup.union_size()))
} }
// Or(Or(Int, Str), Nat) == 3 // Or(Or(Int, Str), Nat) == 3
Self::Or(l, r) => l.union_size() + r.union_size(), Self::Or(tys) => tys.len(),
Self::Refinement(refine) => refine.t.union_size(), Self::Refinement(refine) => refine.t.union_size(),
Self::Ref(t) => t.union_size(), Self::Ref(t) => t.union_size(),
Self::RefMut { before, after: _ } => before.union_size(), Self::RefMut { before, after: _ } => before.union_size(),
Self::And(lhs, rhs) => lhs.union_size().max(rhs.union_size()), Self::And(tys) => tys.iter().map(|ty| ty.union_size()).max().unwrap_or(1),
Self::Not(ty) => ty.union_size(), Self::Not(ty) => ty.union_size(),
Self::Callable { param_ts, return_t } => param_ts Self::Callable { param_ts, return_t } => param_ts
.iter() .iter()
@ -2608,7 +2651,7 @@ impl Type {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_refinement(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_refinement(),
Self::Refinement(_) => true, Self::Refinement(_) => true,
Self::And(l, r) => l.is_refinement() && r.is_refinement(), Self::And(tys) => tys.iter().any(|t| t.is_refinement()),
_ => false, _ => false,
} }
} }
@ -2617,6 +2660,7 @@ impl Type {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_singleton_refinement(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_singleton_refinement(),
Self::Refinement(refine) => matches!(refine.pred.as_ref(), Predicate::Equal { .. }), Self::Refinement(refine) => matches!(refine.pred.as_ref(), Predicate::Equal { .. }),
Self::And(tys) => tys.iter().any(|t| t.is_singleton_refinement()),
_ => false, _ => false,
} }
} }
@ -2626,6 +2670,7 @@ impl Type {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_record(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_record(),
Self::Record(_) => true, Self::Record(_) => true,
Self::Refinement(refine) => refine.t.is_record(), Self::Refinement(refine) => refine.t.is_record(),
Self::And(tys) => tys.iter().any(|t| t.is_record()),
_ => false, _ => false,
} }
} }
@ -2639,6 +2684,7 @@ impl Type {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_erg_module(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_erg_module(),
Self::Refinement(refine) => refine.t.is_erg_module(), Self::Refinement(refine) => refine.t.is_erg_module(),
Self::Poly { name, .. } => &name[..] == "Module", Self::Poly { name, .. } => &name[..] == "Module",
Self::And(tys) => tys.iter().any(|t| t.is_erg_module()),
_ => false, _ => false,
} }
} }
@ -2648,6 +2694,7 @@ impl Type {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_py_module(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_py_module(),
Self::Refinement(refine) => refine.t.is_py_module(), Self::Refinement(refine) => refine.t.is_py_module(),
Self::Poly { name, .. } => &name[..] == "PyModule", Self::Poly { name, .. } => &name[..] == "PyModule",
Self::And(tys) => tys.iter().any(|t| t.is_py_module()),
_ => false, _ => false,
} }
} }
@ -2658,7 +2705,7 @@ impl Type {
Self::Refinement(refine) => refine.t.is_method(), Self::Refinement(refine) => refine.t.is_method(),
Self::Subr(subr) => subr.is_method(), Self::Subr(subr) => subr.is_method(),
Self::Quantified(quant) => quant.is_method(), Self::Quantified(quant) => quant.is_method(),
Self::And(l, r) => l.is_method() && r.is_method(), Self::And(tys) => tys.iter().any(|t| t.is_method()),
_ => false, _ => false,
} }
} }
@ -2669,7 +2716,7 @@ impl Type {
Self::Subr(_) => true, Self::Subr(_) => true,
Self::Quantified(quant) => quant.is_subr(), Self::Quantified(quant) => quant.is_subr(),
Self::Refinement(refine) => refine.t.is_subr(), Self::Refinement(refine) => refine.t.is_subr(),
Self::And(l, r) => l.is_subr() && r.is_subr(), Self::And(tys) => tys.iter().any(|t| t.is_subr()),
_ => false, _ => false,
} }
} }
@ -2680,7 +2727,10 @@ impl Type {
Self::Subr(subr) => Some(subr.kind), Self::Subr(subr) => Some(subr.kind),
Self::Refinement(refine) => refine.t.subr_kind(), Self::Refinement(refine) => refine.t.subr_kind(),
Self::Quantified(quant) => quant.subr_kind(), Self::Quantified(quant) => quant.subr_kind(),
Self::And(l, r) => l.subr_kind().and_then(|k| r.subr_kind().map(|k2| k | k2)), Self::And(tys) => tys
.iter()
.filter_map(|t| t.subr_kind())
.fold(None, |a, b| Some(a? | b)),
_ => None, _ => None,
} }
} }
@ -2690,7 +2740,7 @@ impl Type {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_quantified_subr(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_quantified_subr(),
Self::Quantified(_) => true, Self::Quantified(_) => true,
Self::Refinement(refine) => refine.t.is_quantified_subr(), Self::Refinement(refine) => refine.t.is_quantified_subr(),
Self::And(l, r) => l.is_quantified_subr() && r.is_quantified_subr(), Self::And(tys) => tys.iter().any(|t| t.is_quantified_subr()),
_ => false, _ => false,
} }
} }
@ -2727,6 +2777,7 @@ impl Type {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_iterable(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_iterable(),
Self::Poly { name, .. } => &name[..] == "Iterable", Self::Poly { name, .. } => &name[..] == "Iterable",
Self::Refinement(refine) => refine.t.is_iterable(), Self::Refinement(refine) => refine.t.is_iterable(),
Self::And(tys) => tys.iter().any(|t| t.is_iterable()),
_ => false, _ => false,
} }
} }
@ -2817,6 +2868,7 @@ impl Type {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_structural(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_structural(),
Self::Structural(_) => true, Self::Structural(_) => true,
Self::Refinement(refine) => refine.t.is_structural(), Self::Refinement(refine) => refine.t.is_structural(),
Self::And(tys) => tys.iter().any(|t| t.is_structural()),
_ => false, _ => false,
} }
} }
@ -2826,6 +2878,7 @@ impl Type {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_failure(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_failure(),
Self::Refinement(refine) => refine.t.is_failure(), Self::Refinement(refine) => refine.t.is_failure(),
Self::Failure => true, Self::Failure => true,
Self::And(tys) => tys.iter().any(|t| t.is_failure()),
_ => false, _ => false,
} }
} }
@ -2902,8 +2955,8 @@ impl Type {
Self::ProjCall { lhs, args, .. } => { Self::ProjCall { lhs, args, .. } => {
lhs.contains_tvar(target) || args.iter().any(|t| t.contains_tvar(target)) lhs.contains_tvar(target) || args.iter().any(|t| t.contains_tvar(target))
} }
Self::And(lhs, rhs) => lhs.contains_tvar(target) || rhs.contains_tvar(target), Self::And(tys) => tys.iter().any(|t| t.contains_tvar(target)),
Self::Or(lhs, rhs) => lhs.contains_tvar(target) || rhs.contains_tvar(target), Self::Or(tys) => tys.iter().any(|t| t.contains_tvar(target)),
Self::Not(t) => t.contains_tvar(target), Self::Not(t) => t.contains_tvar(target),
Self::Ref(t) => t.contains_tvar(target), Self::Ref(t) => t.contains_tvar(target),
Self::RefMut { before, after } => { Self::RefMut { before, after } => {
@ -2962,8 +3015,8 @@ impl Type {
Self::ProjCall { lhs, args, .. } => { Self::ProjCall { lhs, args, .. } => {
lhs.has_type_satisfies(f) || args.iter().any(|t| t.has_type_satisfies(f)) lhs.has_type_satisfies(f) || args.iter().any(|t| t.has_type_satisfies(f))
} }
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => { Self::And(tys) | Self::Or(tys) => {
lhs.has_type_satisfies(f) || rhs.has_type_satisfies(f) tys.iter().any(|t| t.has_type_satisfies(f))
} }
Self::Not(t) => t.has_type_satisfies(f), Self::Not(t) => t.has_type_satisfies(f),
Self::Ref(t) => t.has_type_satisfies(f), Self::Ref(t) => t.has_type_satisfies(f),
@ -3030,8 +3083,8 @@ impl Type {
Self::ProjCall { lhs, args, .. } => { Self::ProjCall { lhs, args, .. } => {
lhs.contains_type(target) || args.iter().any(|t| t.contains_type(target)) lhs.contains_type(target) || args.iter().any(|t| t.contains_type(target))
} }
Self::And(lhs, rhs) => lhs.contains_type(target) || rhs.contains_type(target), Self::And(tys) => tys.iter().any(|t| t.contains_type(target)),
Self::Or(lhs, rhs) => lhs.contains_type(target) || rhs.contains_type(target), Self::Or(tys) => tys.iter().any(|t| t.contains_type(target)),
Self::Not(t) => t.contains_type(target), Self::Not(t) => t.contains_type(target),
Self::Ref(t) => t.contains_type(target), Self::Ref(t) => t.contains_type(target),
Self::RefMut { before, after } => { Self::RefMut { before, after } => {
@ -3068,8 +3121,8 @@ impl Type {
Self::ProjCall { lhs, args, .. } => { Self::ProjCall { lhs, args, .. } => {
lhs.contains_tp(target) || args.iter().any(|t| t.contains_tp(target)) lhs.contains_tp(target) || args.iter().any(|t| t.contains_tp(target))
} }
Self::And(lhs, rhs) => lhs.contains_tp(target) || rhs.contains_tp(target), Self::And(tys) => tys.iter().any(|t| t.contains_tp(target)),
Self::Or(lhs, rhs) => lhs.contains_tp(target) || rhs.contains_tp(target), Self::Or(tys) => tys.iter().any(|t| t.contains_tp(target)),
Self::Not(t) => t.contains_tp(target), Self::Not(t) => t.contains_tp(target),
Self::Ref(t) => t.contains_tp(target), Self::Ref(t) => t.contains_tp(target),
Self::RefMut { before, after } => { Self::RefMut { before, after } => {
@ -3102,8 +3155,8 @@ impl Type {
Self::ProjCall { lhs, args, .. } => { Self::ProjCall { lhs, args, .. } => {
lhs.contains_value(target) || args.iter().any(|t| t.contains_value(target)) lhs.contains_value(target) || args.iter().any(|t| t.contains_value(target))
} }
Self::And(lhs, rhs) => lhs.contains_value(target) || rhs.contains_value(target), Self::And(tys) => tys.iter().any(|t| t.contains_value(target)),
Self::Or(lhs, rhs) => lhs.contains_value(target) || rhs.contains_value(target), Self::Or(tys) => tys.iter().any(|t| t.contains_value(target)),
Self::Not(t) => t.contains_value(target), Self::Not(t) => t.contains_value(target),
Self::Ref(t) => t.contains_value(target), Self::Ref(t) => t.contains_value(target),
Self::RefMut { before, after } => { Self::RefMut { before, after } => {
@ -3146,9 +3199,7 @@ impl Type {
Self::ProjCall { lhs, args, .. } => { Self::ProjCall { lhs, args, .. } => {
lhs.contains_type(self) || args.iter().any(|t| t.contains_type(self)) lhs.contains_type(self) || args.iter().any(|t| t.contains_type(self))
} }
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => { Self::And(tys) | Self::Or(tys) => tys.iter().any(|t| t.contains_type(self)),
lhs.contains_type(self) || rhs.contains_type(self)
}
Self::Not(t) => t.contains_type(self), Self::Not(t) => t.contains_type(self),
Self::Ref(t) => t.contains_type(self), Self::Ref(t) => t.contains_type(self),
Self::RefMut { before, after } => { Self::RefMut { before, after } => {
@ -3218,9 +3269,9 @@ impl Type {
Self::Inf => Str::ever("Inf"), Self::Inf => Str::ever("Inf"),
Self::NegInf => Str::ever("NegInf"), Self::NegInf => Str::ever("NegInf"),
Self::Mono(name) => name.clone(), Self::Mono(name) => name.clone(),
Self::And(_, _) => Str::ever("And"), Self::And(_) => Str::ever("And"),
Self::Not(_) => Str::ever("Not"), Self::Not(_) => Str::ever("Not"),
Self::Or(_, _) => Str::ever("Or"), Self::Or(_) => Str::ever("Or"),
Self::Ref(_) => Str::ever("Ref"), Self::Ref(_) => Str::ever("Ref"),
Self::RefMut { .. } => Str::ever("RefMut"), Self::RefMut { .. } => Str::ever("RefMut"),
Self::Subr(SubrType { Self::Subr(SubrType {
@ -3310,7 +3361,7 @@ impl Type {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_intersec(typ), Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_intersec(typ),
Self::Refinement(refine) => refine.t.contains_intersec(typ), Self::Refinement(refine) => refine.t.contains_intersec(typ),
Self::And(t1, t2) => t1.contains_intersec(typ) || t2.contains_intersec(typ), Self::And(tys) => tys.iter().any(|t| t.contains_intersec(typ)),
_ => self == typ, _ => self == typ,
} }
} }
@ -3319,7 +3370,16 @@ impl Type {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().union_pair(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().union_pair(),
Self::Refinement(refine) => refine.t.union_pair(), Self::Refinement(refine) => refine.t.union_pair(),
Self::Or(t1, t2) => Some((*t1.clone(), *t2.clone())), Self::Or(tys) if tys.len() == 2 => {
let mut iter = tys.iter();
Some((iter.next().unwrap().clone(), iter.next().unwrap().clone()))
}
Self::Or(tys) => {
let mut iter = tys.iter();
let t1 = iter.next().unwrap().clone();
let t2 = iter.cloned().collect();
Some((t1, Type::Or(t2)))
}
_ => None, _ => None,
} }
} }
@ -3329,7 +3389,7 @@ impl Type {
match self { match self {
Type::FreeVar(fv) if fv.is_linked() => fv.crack().contains_union(typ), Type::FreeVar(fv) if fv.is_linked() => fv.crack().contains_union(typ),
Type::Refinement(refine) => refine.t.contains_union(typ), Type::Refinement(refine) => refine.t.contains_union(typ),
Type::Or(t1, t2) => t1.contains_union(typ) || t2.contains_union(typ), Type::Or(tys) => tys.iter().any(|t| t.contains_union(typ)),
_ => self == typ, _ => self == typ,
} }
} }
@ -3343,11 +3403,7 @@ impl Type {
.into_iter() .into_iter()
.map(|t| t.quantify()) .map(|t| t.quantify())
.collect(), .collect(),
Type::And(t1, t2) => { Type::And(tys) => tys.iter().cloned().collect(),
let mut types = t1.intersection_types();
types.extend(t2.intersection_types());
types
}
_ => vec![self.clone()], _ => vec![self.clone()],
} }
} }
@ -3423,9 +3479,7 @@ impl Type {
match self { match self {
Self::FreeVar(fv) if fv.is_unbound() => true, Self::FreeVar(fv) if fv.is_unbound() => true,
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_totally_unbound(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_totally_unbound(),
Self::Or(t1, t2) | Self::And(t1, t2) => { Self::Or(tys) | Self::And(tys) => tys.iter().all(|t| t.is_totally_unbound()),
t1.is_totally_unbound() && t2.is_totally_unbound()
}
Self::Not(t) => t.is_totally_unbound(), Self::Not(t) => t.is_totally_unbound(),
_ => false, _ => false,
} }
@ -3532,9 +3586,10 @@ impl Type {
sub.destructive_coerce(); sub.destructive_coerce();
self.destructive_link(&sub); self.destructive_link(&sub);
} }
Type::And(l, r) | Type::Or(l, r) => { Type::And(tys) | Type::Or(tys) => {
l.destructive_coerce(); for t in tys {
r.destructive_coerce(); t.destructive_coerce();
}
} }
Type::Not(l) => l.destructive_coerce(), Type::Not(l) => l.destructive_coerce(),
Type::Poly { params, .. } => { Type::Poly { params, .. } => {
@ -3587,9 +3642,10 @@ impl Type {
sub.undoable_coerce(list); sub.undoable_coerce(list);
self.undoable_link(&sub, list); self.undoable_link(&sub, list);
} }
Type::And(l, r) | Type::Or(l, r) => { Type::And(tys) | Type::Or(tys) => {
l.undoable_coerce(list); for t in tys {
r.undoable_coerce(list); t.undoable_coerce(list);
}
} }
Type::Not(l) => l.undoable_coerce(list), Type::Not(l) => l.undoable_coerce(list),
Type::Poly { params, .. } => { Type::Poly { params, .. } => {
@ -3648,7 +3704,9 @@ impl Type {
.map(|t| t.qvars_inner()) .map(|t| t.qvars_inner())
.unwrap_or_else(|| set! {}), .unwrap_or_else(|| set! {}),
), ),
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => lhs.qvars_inner().concat(rhs.qvars_inner()), Self::And(tys) | Self::Or(tys) => tys
.iter()
.fold(set! {}, |acc, t| acc.concat(t.qvars_inner())),
Self::Not(ty) => ty.qvars_inner(), Self::Not(ty) => ty.qvars_inner(),
Self::Callable { param_ts, return_t } => param_ts Self::Callable { param_ts, return_t } => param_ts
.iter() .iter()
@ -3716,7 +3774,7 @@ impl Type {
Self::RefMut { before, after } => { Self::RefMut { before, after } => {
before.has_qvar() || after.as_ref().map(|t| t.has_qvar()).unwrap_or(false) before.has_qvar() || after.as_ref().map(|t| t.has_qvar()).unwrap_or(false)
} }
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => lhs.has_qvar() || rhs.has_qvar(), Self::And(tys) | Self::Or(tys) => tys.iter().any(|t| t.has_qvar()),
Self::Not(ty) => ty.has_qvar(), Self::Not(ty) => ty.has_qvar(),
Self::Callable { param_ts, return_t } => { Self::Callable { param_ts, return_t } => {
param_ts.iter().any(|t| t.has_qvar()) || return_t.has_qvar() param_ts.iter().any(|t| t.has_qvar()) || return_t.has_qvar()
@ -3769,9 +3827,7 @@ impl Type {
.map(|t| t.has_undoable_linked_var()) .map(|t| t.has_undoable_linked_var())
.unwrap_or(false) .unwrap_or(false)
} }
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => { Self::And(tys) | Self::Or(tys) => tys.iter().any(|t| t.has_undoable_linked_var()),
lhs.has_undoable_linked_var() || rhs.has_undoable_linked_var()
}
Self::Not(ty) => ty.has_undoable_linked_var(), Self::Not(ty) => ty.has_undoable_linked_var(),
Self::Callable { param_ts, return_t } => { Self::Callable { param_ts, return_t } => {
param_ts.iter().any(|t| t.has_undoable_linked_var()) param_ts.iter().any(|t| t.has_undoable_linked_var())
@ -3810,9 +3866,7 @@ impl Type {
before.has_unbound_var() before.has_unbound_var()
|| after.as_ref().map(|t| t.has_unbound_var()).unwrap_or(false) || after.as_ref().map(|t| t.has_unbound_var()).unwrap_or(false)
} }
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => { Self::And(tys) | Self::Or(tys) => tys.iter().any(|t| t.has_unbound_var()),
lhs.has_unbound_var() || rhs.has_unbound_var()
}
Self::Not(ty) => ty.has_unbound_var(), Self::Not(ty) => ty.has_unbound_var(),
Self::Callable { param_ts, return_t } => { Self::Callable { param_ts, return_t } => {
param_ts.iter().any(|t| t.has_unbound_var()) || return_t.has_unbound_var() param_ts.iter().any(|t| t.has_unbound_var()) || return_t.has_unbound_var()
@ -3867,7 +3921,7 @@ impl Type {
Self::Refinement(refine) => refine.t.typarams_len(), Self::Refinement(refine) => refine.t.typarams_len(),
// REVIEW: // REVIEW:
Self::Ref(_) | Self::RefMut { .. } => Some(1), Self::Ref(_) | Self::RefMut { .. } => Some(1),
Self::And(_, _) | Self::Or(_, _) => Some(2), Self::And(tys) | Self::Or(tys) => Some(tys.len()),
Self::Not(_) => Some(1), Self::Not(_) => Some(1),
Self::Subr(subr) => Some( Self::Subr(subr) => Some(
subr.non_default_params.len() subr.non_default_params.len()
@ -3933,9 +3987,7 @@ impl Type {
Self::FreeVar(_unbound) => vec![], Self::FreeVar(_unbound) => vec![],
Self::Refinement(refine) => refine.t.typarams(), Self::Refinement(refine) => refine.t.typarams(),
Self::Ref(t) | Self::RefMut { before: t, .. } => vec![TyParam::t(*t.clone())], Self::Ref(t) | Self::RefMut { before: t, .. } => vec![TyParam::t(*t.clone())],
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => { Self::And(tys) | Self::Or(tys) => tys.iter().cloned().map(TyParam::t).collect(),
vec![TyParam::t(*lhs.clone()), TyParam::t(*rhs.clone())]
}
Self::Not(t) => vec![TyParam::t(*t.clone())], Self::Not(t) => vec![TyParam::t(*t.clone())],
Self::Subr(subr) => subr.typarams(), Self::Subr(subr) => subr.typarams(),
Self::Quantified(quant) => quant.typarams(), Self::Quantified(quant) => quant.typarams(),
@ -4156,8 +4208,8 @@ impl Type {
let r = r.iter().map(|(k, v)| (k.clone(), v.derefine())).collect(); let r = r.iter().map(|(k, v)| (k.clone(), v.derefine())).collect();
Self::NamedTuple(r) Self::NamedTuple(r)
} }
Self::And(l, r) => l.derefine() & r.derefine(), Self::And(tys) => Self::checked_and(tys.iter().map(|t| t.derefine()).collect()),
Self::Or(l, r) => l.derefine() | r.derefine(), Self::Or(tys) => Self::checked_or(tys.iter().map(|t| t.derefine()).collect()),
Self::Not(ty) => !ty.derefine(), Self::Not(ty) => !ty.derefine(),
Self::Proj { lhs, rhs } => lhs.derefine().proj(rhs.clone()), Self::Proj { lhs, rhs } => lhs.derefine().proj(rhs.clone()),
Self::ProjCall { Self::ProjCall {
@ -4224,22 +4276,28 @@ impl Type {
}); });
self self
} }
Self::And(l, r) => { Self::And(tys) => Self::checked_and(
if l.addr_eq(target) { tys.into_iter()
return r.eliminate_subsup(target); .filter_map(|t| {
} else if r.addr_eq(target) { if t.addr_eq(target) {
return l.eliminate_subsup(target); None
} else {
Some(t.eliminate_subsup(target))
} }
l.eliminate_subsup(target) & r.eliminate_subsup(target) })
} .collect(),
Self::Or(l, r) => { ),
if l.addr_eq(target) { Self::Or(tys) => Self::checked_or(
return r.eliminate_subsup(target); tys.into_iter()
} else if r.addr_eq(target) { .filter_map(|t| {
return l.eliminate_subsup(target); if t.addr_eq(target) {
} None
l.eliminate_subsup(target) | r.eliminate_subsup(target) } else {
Some(t.eliminate_subsup(target))
} }
})
.collect(),
),
other => other, other => other,
} }
} }
@ -4294,8 +4352,16 @@ impl Type {
before: Box::new(before.eliminate_recursion(target)), before: Box::new(before.eliminate_recursion(target)),
after: after.map(|t| Box::new(t.eliminate_recursion(target))), after: after.map(|t| Box::new(t.eliminate_recursion(target))),
}, },
Self::And(l, r) => l.eliminate_recursion(target) & r.eliminate_recursion(target), Self::And(tys) => Self::checked_and(
Self::Or(l, r) => l.eliminate_recursion(target) | r.eliminate_recursion(target), tys.into_iter()
.map(|t| t.eliminate_recursion(target))
.collect(),
),
Self::Or(tys) => Self::checked_or(
tys.into_iter()
.map(|t| t.eliminate_recursion(target))
.collect(),
),
Self::Not(ty) => !ty.eliminate_recursion(target), Self::Not(ty) => !ty.eliminate_recursion(target),
Self::Proj { lhs, rhs } => lhs.eliminate_recursion(target).proj(rhs), Self::Proj { lhs, rhs } => lhs.eliminate_recursion(target).proj(rhs),
Self::ProjCall { Self::ProjCall {
@ -4448,8 +4514,8 @@ impl Type {
before: Box::new(before.map(f)), before: Box::new(before.map(f)),
after: after.map(|t| Box::new(t.map(f))), after: after.map(|t| Box::new(t.map(f))),
}, },
Self::And(l, r) => l.map(f) & r.map(f), Self::And(tys) => Self::checked_and(tys.into_iter().map(|t| t.map(f)).collect()),
Self::Or(l, r) => l.map(f) | r.map(f), Self::Or(tys) => Self::checked_or(tys.into_iter().map(|t| t.map(f)).collect()),
Self::Not(ty) => !ty.map(f), Self::Not(ty) => !ty.map(f),
Self::Proj { lhs, rhs } => lhs.map(f).proj(rhs), Self::Proj { lhs, rhs } => lhs.map(f).proj(rhs),
Self::ProjCall { Self::ProjCall {
@ -4542,8 +4608,12 @@ impl Type {
before: Box::new(before._replace_tp(target, to)), before: Box::new(before._replace_tp(target, to)),
after: after.map(|t| Box::new(t._replace_tp(target, to))), after: after.map(|t| Box::new(t._replace_tp(target, to))),
}, },
Self::And(l, r) => l._replace_tp(target, to) & r._replace_tp(target, to), Self::And(tys) => {
Self::Or(l, r) => l._replace_tp(target, to) | r._replace_tp(target, to), Self::checked_and(tys.into_iter().map(|t| t._replace_tp(target, to)).collect())
}
Self::Or(tys) => {
Self::checked_or(tys.into_iter().map(|t| t._replace_tp(target, to)).collect())
}
Self::Not(ty) => !ty._replace_tp(target, to), Self::Not(ty) => !ty._replace_tp(target, to),
Self::Proj { lhs, rhs } => lhs._replace_tp(target, to).proj(rhs), Self::Proj { lhs, rhs } => lhs._replace_tp(target, to).proj(rhs),
Self::ProjCall { Self::ProjCall {
@ -4619,8 +4689,8 @@ impl Type {
before: Box::new(before.map_tp(f)), before: Box::new(before.map_tp(f)),
after: after.map(|t| Box::new(t.map_tp(f))), after: after.map(|t| Box::new(t.map_tp(f))),
}, },
Self::And(l, r) => l.map_tp(f) & r.map_tp(f), Self::And(tys) => Self::checked_and(tys.into_iter().map(|t| t.map_tp(f)).collect()),
Self::Or(l, r) => l.map_tp(f) | r.map_tp(f), Self::Or(tys) => Self::checked_or(tys.into_iter().map(|t| t.map_tp(f)).collect()),
Self::Not(ty) => !ty.map_tp(f), Self::Not(ty) => !ty.map_tp(f),
Self::Proj { lhs, rhs } => lhs.map_tp(f).proj(rhs), Self::Proj { lhs, rhs } => lhs.map_tp(f).proj(rhs),
Self::ProjCall { Self::ProjCall {
@ -4708,8 +4778,16 @@ impl Type {
after, after,
}) })
} }
Self::And(l, r) => Ok(l.try_map_tp(f)? & r.try_map_tp(f)?), Self::And(tys) => Ok(Self::checked_and(
Self::Or(l, r) => Ok(l.try_map_tp(f)? | r.try_map_tp(f)?), tys.into_iter()
.map(|t| t.try_map_tp(f))
.collect::<Result<_, _>>()?,
)),
Self::Or(tys) => Ok(Self::checked_or(
tys.into_iter()
.map(|t| t.try_map_tp(f))
.collect::<Result<_, _>>()?,
)),
Self::Not(ty) => Ok(!ty.try_map_tp(f)?), Self::Not(ty) => Ok(!ty.try_map_tp(f)?),
Self::Proj { lhs, rhs } => Ok(lhs.try_map_tp(f)?.proj(rhs)), Self::Proj { lhs, rhs } => Ok(lhs.try_map_tp(f)?.proj(rhs)),
Self::ProjCall { Self::ProjCall {
@ -4742,12 +4820,28 @@ impl Type {
*refine.t = refine.t.replace_param(target, to); *refine.t = refine.t.replace_param(target, to);
Self::Refinement(refine) Self::Refinement(refine)
} }
Self::And(l, r) => l.replace_param(target, to) & r.replace_param(target, to), Self::And(tys) => Self::And(
tys.into_iter()
.map(|t| t.replace_param(target, to))
.collect(),
),
Self::Guard(guard) => Self::Guard(guard.replace_param(target, to)), Self::Guard(guard) => Self::Guard(guard.replace_param(target, to)),
_ => self, _ => self,
} }
} }
pub fn eliminate_and_or(&mut self) {
match self {
Self::And(tys) if tys.len() == 1 => {
*self = tys.take_all().into_iter().next().unwrap();
}
Self::Or(tys) if tys.len() == 1 => {
*self = tys.take_all().into_iter().next().unwrap();
}
_ => {}
}
}
pub fn replace_params<'l, 'r>( pub fn replace_params<'l, 'r>(
mut self, mut self,
target: impl Iterator<Item = &'l str>, target: impl Iterator<Item = &'l str>,
@ -4815,8 +4909,8 @@ impl Type {
} }
Self::NamedTuple(r) Self::NamedTuple(r)
} }
Self::And(l, r) => l.normalize() & r.normalize(), Self::And(tys) => Self::checked_and(tys.into_iter().map(|t| t.normalize()).collect()),
Self::Or(l, r) => l.normalize() | r.normalize(), Self::Or(tys) => Self::checked_or(tys.into_iter().map(|t| t.normalize()).collect()),
Self::Not(ty) => !ty.normalize(), Self::Not(ty) => !ty.normalize(),
Self::Structural(ty) => ty.normalize().structuralize(), Self::Structural(ty) => ty.normalize().structuralize(),
Self::Quantified(quant) => quant.normalize().quantify(), Self::Quantified(quant) => quant.normalize().quantify(),
@ -4848,14 +4942,36 @@ impl Type {
free.get_sub().unwrap_or(self.clone()) free.get_sub().unwrap_or(self.clone())
} else { } else {
match self { match self {
Self::And(l, r) => l.lower_bounded() & r.lower_bounded(), Self::And(tys) => {
Self::Or(l, r) => l.lower_bounded() | r.lower_bounded(), Self::checked_and(tys.iter().map(|t| t.lower_bounded()).collect())
}
Self::Or(tys) => Self::checked_or(tys.iter().map(|t| t.lower_bounded()).collect()),
Self::Not(ty) => !ty.lower_bounded(), Self::Not(ty) => !ty.lower_bounded(),
_ => self.clone(), _ => self.clone(),
} }
} }
} }
/// ```erg
/// assert Int.upper_bounded() == Int
/// assert ?T(<: Str).upper_bounded() == Str
/// assert (?T(<: Str) or ?U(<: Int)).upper_bounded() == (Str or Int)
/// ```
pub fn upper_bounded(&self) -> Type {
if let Ok(free) = <&FreeTyVar>::try_from(self) {
free.get_super().unwrap_or(self.clone())
} else {
match self {
Self::And(tys) => {
Self::checked_and(tys.iter().map(|t| t.upper_bounded()).collect())
}
Self::Or(tys) => Self::checked_or(tys.iter().map(|t| t.upper_bounded()).collect()),
Self::Not(ty) => !ty.upper_bounded(),
_ => self.clone(),
}
}
}
pub(crate) fn addr_eq(&self, other: &Type) -> bool { pub(crate) fn addr_eq(&self, other: &Type) -> bool {
match (self, other) { match (self, other) {
(Self::FreeVar(slf), _) if slf.is_linked() => slf.crack().addr_eq(other), (Self::FreeVar(slf), _) if slf.is_linked() => slf.crack().addr_eq(other),
@ -5018,7 +5134,7 @@ impl Type {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().ands(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().ands(),
Self::Refinement(refine) => refine.t.ands(), Self::Refinement(refine) => refine.t.ands(),
Self::And(l, r) => l.ands().union(&r.ands()), Self::And(tys) => tys.clone(),
_ => set![self.clone()], _ => set![self.clone()],
} }
} }
@ -5031,7 +5147,7 @@ impl Type {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().ors(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().ors(),
Self::Refinement(refine) => refine.t.ors(), Self::Refinement(refine) => refine.t.ors(),
Self::Or(l, r) => l.ors().union(&r.ors()), Self::Or(tys) => tys.clone(),
_ => set![self.clone()], _ => set![self.clone()],
} }
} }
@ -5076,7 +5192,7 @@ impl Type {
Self::Callable { param_ts, .. } => { Self::Callable { param_ts, .. } => {
param_ts.iter().flat_map(|t| t.contained_ts()).collect() param_ts.iter().flat_map(|t| t.contained_ts()).collect()
} }
Self::And(l, r) | Self::Or(l, r) => l.contained_ts().union(&r.contained_ts()), Self::And(tys) | Self::Or(tys) => tys.iter().flat_map(|t| t.contained_ts()).collect(),
Self::Not(t) => t.contained_ts(), Self::Not(t) => t.contained_ts(),
Self::Bounded { sub, sup } => sub.contained_ts().union(&sup.contained_ts()), Self::Bounded { sub, sup } => sub.contained_ts().union(&sup.contained_ts()),
Self::Quantified(ty) | Self::Structural(ty) => ty.contained_ts(), Self::Quantified(ty) | Self::Structural(ty) => ty.contained_ts(),
@ -5145,9 +5261,18 @@ impl Type {
} }
return_t.dereference(); return_t.dereference();
} }
Self::And(l, r) | Self::Or(l, r) => { Self::And(tys) | Self::Or(tys) => {
l.dereference(); *tys = tys
r.dereference(); .take_all()
.into_iter()
.map(|mut t| {
t.dereference();
t
})
.collect();
if tys.len() == 1 {
*self = tys.take_all().into_iter().next().unwrap();
}
} }
Self::Not(ty) => { Self::Not(ty) => {
ty.dereference(); ty.dereference();
@ -5255,7 +5380,7 @@ impl Type {
set.extend(return_t.variables()); set.extend(return_t.variables());
set set
} }
Self::And(l, r) | Self::Or(l, r) => l.variables().union(&r.variables()), Self::And(tys) | Self::Or(tys) => tys.iter().flat_map(|t| t.variables()).collect(),
Self::Not(ty) => ty.variables(), Self::Not(ty) => ty.variables(),
Self::Bounded { sub, sup } => sub.variables().union(&sup.variables()), Self::Bounded { sub, sup } => sub.variables().union(&sup.variables()),
Self::Quantified(ty) | Self::Structural(ty) => ty.variables(), Self::Quantified(ty) | Self::Structural(ty) => ty.variables(),
@ -5367,13 +5492,16 @@ impl<'t> ReplaceTable<'t> {
self.iterate(l, r); self.iterate(l, r);
} }
} }
(Type::And(l, r), Type::And(l2, r2)) => { // FIXME:
self.iterate(l, l2); (Type::And(tys), Type::And(tys2)) => {
self.iterate(r, r2); for (l, r) in tys.iter().zip(tys2.iter()) {
self.iterate(l, r);
}
}
(Type::Or(tys), Type::Or(tys2)) => {
for (l, r) in tys.iter().zip(tys2.iter()) {
self.iterate(l, r);
} }
(Type::Or(l, r), Type::Or(l2, r2)) => {
self.iterate(l, l2);
self.iterate(r, r2);
} }
(Type::Not(t), Type::Not(t2)) => { (Type::Not(t), Type::Not(t2)) => {
self.iterate(t, t2); self.iterate(t, t2);