mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 12:14:43 +00:00
fix: type-var comparison bug
This commit is contained in:
parent
5bbb421b7f
commit
b84bd19237
2 changed files with 66 additions and 29 deletions
|
@ -482,7 +482,7 @@ impl Context {
|
||||||
// ?T(:> Int, <: Eq) :> ?U(:> Nat, <: Eq)
|
// ?T(:> Int, <: Eq) :> ?U(:> Nat, <: Eq)
|
||||||
(FreeVar(lfv), FreeVar(rfv)) => match (lfv.get_subsup(), rfv.get_subsup()) {
|
(FreeVar(lfv), FreeVar(rfv)) => match (lfv.get_subsup(), rfv.get_subsup()) {
|
||||||
(Some((l_sub, l_supe)), Some((r_sub, _))) => {
|
(Some((l_sub, l_supe)), Some((r_sub, _))) => {
|
||||||
self.related(&l_sub, &r_sub) && self.supertype_of(&l_supe, &r_sub)
|
self.supertype_of(&l_supe, &r_sub) && self.related(&l_sub, &r_sub)
|
||||||
}
|
}
|
||||||
(Some((l_sub, _)), None) if &l_sub == rhs => true,
|
(Some((l_sub, _)), None) if &l_sub == rhs => true,
|
||||||
(None, Some((_, r_sup))) if lhs == &r_sup => true,
|
(None, Some((_, r_sup))) if lhs == &r_sup => true,
|
||||||
|
|
|
@ -177,18 +177,34 @@ impl<'c> Substituter<'c> {
|
||||||
qt: &Type,
|
qt: &Type,
|
||||||
st: &Type,
|
st: &Type,
|
||||||
) -> EvalResult<Option<Self>> {
|
) -> EvalResult<Option<Self>> {
|
||||||
let qtps = qt.typarams();
|
let mut qtps = qt.typarams();
|
||||||
let mut stps = st.typarams();
|
let mut stps = st.typarams();
|
||||||
// Or, And are commutative, choose fitting order
|
// Or, And are commutative, choose fitting order
|
||||||
if qt.qual_name() == st.qual_name() && (st.qual_name() == "Or" || st.qual_name() == "And") {
|
if qt.qual_name() == st.qual_name() {
|
||||||
// REVIEW: correct condition?
|
if st.is_union_type() || st.is_intersection_type() {
|
||||||
if qt != st
|
let mut q_indices = vec![];
|
||||||
&& ctx.covariant_supertype_of_tp(&qtps[0], &stps[1])
|
let mut s_indices = vec![];
|
||||||
&& ctx.covariant_supertype_of_tp(&qtps[1], &stps[0])
|
for (i, qtp) in qtps.iter().enumerate() {
|
||||||
{
|
if let Some(j) = stps.iter().position(|stp| stp == qtp) {
|
||||||
stps.swap(0, 1);
|
q_indices.push(i);
|
||||||
|
s_indices.push(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for q_index in q_indices {
|
||||||
|
qtps[q_index] = TyParam::Failure;
|
||||||
|
}
|
||||||
|
for s_index in s_indices {
|
||||||
|
stps[s_index] = TyParam::Failure;
|
||||||
|
}
|
||||||
|
// REVIEW: correct condition?
|
||||||
|
if qt != st
|
||||||
|
&& ctx.covariant_supertype_of_tp(&qtps[0], &stps[1])
|
||||||
|
&& ctx.covariant_supertype_of_tp(&qtps[1], &stps[0])
|
||||||
|
{
|
||||||
|
stps.swap(0, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if qt.qual_name() != st.qual_name() || qtps.len() != stps.len() {
|
} else {
|
||||||
// e.g. qt: Iterable(T), st: Vec(<: Iterable(Int))
|
// e.g. qt: Iterable(T), st: Vec(<: Iterable(Int))
|
||||||
if let Some(st_sups) = ctx.get_super_types(st) {
|
if let Some(st_sups) = ctx.get_super_types(st) {
|
||||||
for sup in st_sups.skip(1) {
|
for sup in st_sups.skip(1) {
|
||||||
|
@ -198,8 +214,12 @@ impl<'c> Substituter<'c> {
|
||||||
for (sup_tp, stp) in sup_tps.into_iter().zip(stps.into_iter()) {
|
for (sup_tp, stp) in sup_tps.into_iter().zip(stps.into_iter()) {
|
||||||
let _ = child.substitute_typaram(sup_tp, stp);
|
let _ = child.substitute_typaram(sup_tp, stp);
|
||||||
}
|
}
|
||||||
return Self::substitute_typarams(ctx, qt, &sup)
|
if st == &sup {
|
||||||
.map(|opt_subs| opt_subs.map(|sub| sub.with_child(child)));
|
return Ok(Some(child));
|
||||||
|
} else {
|
||||||
|
return Self::substitute_typarams(ctx, qt, &sup)
|
||||||
|
.map(|opt_subs| opt_subs.map(|sub| sub.with_child(child)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,9 +251,33 @@ impl<'c> Substituter<'c> {
|
||||||
qt: &Type,
|
qt: &Type,
|
||||||
st: &Type,
|
st: &Type,
|
||||||
) -> EvalResult<Option<Self>> {
|
) -> EvalResult<Option<Self>> {
|
||||||
let qtps = qt.typarams();
|
let mut qtps = qt.typarams();
|
||||||
let stps = st.typarams();
|
let mut stps = st.typarams();
|
||||||
if qt.qual_name() != st.qual_name() || qtps.len() != stps.len() {
|
if qt.qual_name() == st.qual_name() {
|
||||||
|
if st.is_union_type() || st.is_intersection_type() {
|
||||||
|
let mut q_indices = vec![];
|
||||||
|
let mut s_indices = vec![];
|
||||||
|
for (i, qtp) in qtps.iter().enumerate() {
|
||||||
|
if let Some(j) = stps.iter().position(|stp| stp == qtp) {
|
||||||
|
q_indices.push(i);
|
||||||
|
s_indices.push(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for q_index in q_indices {
|
||||||
|
qtps[q_index] = TyParam::Failure;
|
||||||
|
}
|
||||||
|
for s_index in s_indices {
|
||||||
|
stps[s_index] = TyParam::Failure;
|
||||||
|
}
|
||||||
|
// REVIEW: correct condition?
|
||||||
|
if qt != st
|
||||||
|
&& ctx.covariant_supertype_of_tp(&qtps[0], &stps[1])
|
||||||
|
&& ctx.covariant_supertype_of_tp(&qtps[1], &stps[0])
|
||||||
|
{
|
||||||
|
stps.swap(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// e.g. qt: Iterable(T), st: Vec(<: Iterable(Int))
|
// e.g. qt: Iterable(T), st: Vec(<: Iterable(Int))
|
||||||
if let Some(st_sups) = ctx.get_super_types(st) {
|
if let Some(st_sups) = ctx.get_super_types(st) {
|
||||||
for sup in st_sups.skip(1) {
|
for sup in st_sups.skip(1) {
|
||||||
|
@ -243,8 +287,12 @@ impl<'c> Substituter<'c> {
|
||||||
for (sup_tp, stp) in sup_tps.into_iter().zip(stps.into_iter()) {
|
for (sup_tp, stp) in sup_tps.into_iter().zip(stps.into_iter()) {
|
||||||
let _ = child.overwrite_typaram(sup_tp, stp);
|
let _ = child.overwrite_typaram(sup_tp, stp);
|
||||||
}
|
}
|
||||||
return Self::overwrite_typarams(ctx, qt, &sup)
|
if st == &sup {
|
||||||
.map(|opt_subs| opt_subs.map(|sub| sub.with_child(child)));
|
return Ok(Some(child));
|
||||||
|
} else {
|
||||||
|
return Self::overwrite_typarams(ctx, qt, &sup)
|
||||||
|
.map(|opt_subs| opt_subs.map(|sub| sub.with_child(child)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2058,18 +2106,7 @@ impl Context {
|
||||||
TyParam::erased(t)
|
TyParam::erased(t)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TyParam::Value(val) => {
|
TyParam::Value(val) => TyParam::Value(val),
|
||||||
match val
|
|
||||||
.clone()
|
|
||||||
.try_map_t(&mut |t| self.eval_t_params(t, self.level, &()))
|
|
||||||
{
|
|
||||||
Ok(val) => TyParam::Value(val),
|
|
||||||
Err((_t, es)) => {
|
|
||||||
errs.extend(es);
|
|
||||||
TyParam::Value(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TyParam::ProjCall { obj, attr, args } => {
|
TyParam::ProjCall { obj, attr, args } => {
|
||||||
match self.eval_proj_call(*obj, attr, args, &()) {
|
match self.eval_proj_call(*obj, attr, args, &()) {
|
||||||
Ok(tp) => tp,
|
Ok(tp) => tp,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue