forked from M-Labs/nac3
1
0
Fork 0

modified occur check

This commit is contained in:
pca006132 2021-07-21 16:10:11 +08:00
parent b3d849ea7a
commit 4f81690128
2 changed files with 9 additions and 2 deletions

View File

@ -162,7 +162,7 @@ impl TestEnvironment {
#[test_case(indoc! {" #[test_case(indoc! {"
f = lambda x: True f = lambda x: True
a = [1, 2, 3] a = [1, 2, 3]
b = [f(x) for x in a] b = [f(x) for x in a if f(x)]
"}, "},
[("a", "list[int32]"), ("b", "list[bool]"), ("f", "fn[[x=int32], bool]")].iter().cloned().collect() [("a", "list[int32]"), ("b", "list[bool]"), ("f", "fn[[x=int32], bool]")].iter().cloned().collect()
; "listcomp test")] ; "listcomp test")]

View File

@ -259,12 +259,13 @@ impl Unifier {
let (ty_a, ty_b) = { (ty_a_cell.borrow(), ty_b_cell.borrow()) }; let (ty_a, ty_b) = { (ty_a_cell.borrow(), ty_b_cell.borrow()) };
self.occur_check(a, b)?;
match (&*ty_a, &*ty_b) { match (&*ty_a, &*ty_b) {
(TypeEnum::TVar { .. }, _) => { (TypeEnum::TVar { .. }, _) => {
self.occur_check(a, b)?;
self.set_a_to_b(a, b); self.set_a_to_b(a, b);
} }
(TSeq { map: map1 }, TSeq { .. }) => { (TSeq { map: map1 }, TSeq { .. }) => {
self.occur_check(a, b)?;
drop(ty_b); drop(ty_b);
if let TypeEnum::TSeq { map: map2 } = &mut *ty_b_cell.as_ref().borrow_mut() { if let TypeEnum::TSeq { map: map2 } = &mut *ty_b_cell.as_ref().borrow_mut() {
// unify them to map2 // unify them to map2
@ -281,6 +282,7 @@ impl Unifier {
self.set_a_to_b(a, b); self.set_a_to_b(a, b);
} }
(TSeq { map: map1 }, TTuple { ty: types }) => { (TSeq { map: map1 }, TTuple { ty: types }) => {
self.occur_check(a, b)?;
let len = types.len() as i32; let len = types.len() as i32;
for (k, v) in map1.iter() { for (k, v) in map1.iter() {
// handle negative index // handle negative index
@ -297,6 +299,7 @@ impl Unifier {
self.set_a_to_b(a, b); self.set_a_to_b(a, b);
} }
(TSeq { map: map1 }, TList { ty }) => { (TSeq { map: map1 }, TList { ty }) => {
self.occur_check(a, b)?;
for v in map1.values() { for v in map1.values() {
self.unify(*v, *ty)?; self.unify(*v, *ty)?;
} }
@ -320,6 +323,7 @@ impl Unifier {
self.set_a_to_b(a, b); self.set_a_to_b(a, b);
} }
(TRecord { fields: fields1 }, TRecord { .. }) => { (TRecord { fields: fields1 }, TRecord { .. }) => {
self.occur_check(a, b)?;
drop(ty_b); drop(ty_b);
if let TypeEnum::TRecord { fields: fields2 } = &mut *ty_b_cell.as_ref().borrow_mut() if let TypeEnum::TRecord { fields: fields2 } = &mut *ty_b_cell.as_ref().borrow_mut()
{ {
@ -341,6 +345,7 @@ impl Unifier {
fields: fields2, .. fields: fields2, ..
}, },
) => { ) => {
self.occur_check(a, b)?;
for (key, value) in fields1.iter() { for (key, value) in fields1.iter() {
if let Some(ty) = fields2.get(key) { if let Some(ty) = fields2.get(key) {
self.unify(*ty, *value)?; self.unify(*ty, *value)?;
@ -351,6 +356,7 @@ impl Unifier {
self.set_a_to_b(a, b); self.set_a_to_b(a, b);
} }
(TRecord { .. }, TVirtual { ty }) => { (TRecord { .. }, TVirtual { ty }) => {
self.occur_check(a, b)?;
self.unify(a, *ty)?; self.unify(a, *ty)?;
} }
( (
@ -387,6 +393,7 @@ impl Unifier {
self.set_a_to_b(a, b); self.set_a_to_b(a, b);
} }
(TCall { calls }, TFunc(signature)) => { (TCall { calls }, TFunc(signature)) => {
self.occur_check(a, b)?;
let required: Vec<String> = signature let required: Vec<String> = signature
.args .args
.iter() .iter()