occur check

This commit is contained in:
pca006132 2021-07-15 16:51:55 +08:00
parent d94f25583b
commit c2d00aa762
2 changed files with 9 additions and 2 deletions

View File

@ -242,6 +242,13 @@ mod test {
(("v1", "v2"), "No such attribute b") (("v1", "v2"), "No such attribute b")
; "record obj merge" ; "record obj merge"
)] )]
#[test_case(2,
&[
("v1", "List[v2]"),
],
(("v1", "v2"), "Recursive type is prohibited.")
; "recursive type for lists"
)]
fn test_invalid_unification( fn test_invalid_unification(
variable_count: u32, variable_count: u32,
unify_pairs: &[(&'static str, &'static str)], unify_pairs: &[(&'static str, &'static str)],

View File

@ -216,7 +216,7 @@ impl Unifier {
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 map1 // unify them to map2
for (key, value) in map1.iter() { for (key, value) in map1.iter() {
if let Some(ty) = map2.get(key) { if let Some(ty) = map2.get(key) {
self.unify(*ty, *value)?; self.unify(*ty, *value)?;
@ -377,7 +377,7 @@ impl Unifier {
fn occur_check(&self, a: TypeIndex, b: Type) -> Result<(), String> { fn occur_check(&self, a: TypeIndex, b: Type) -> Result<(), String> {
let i_b = self.unification_table.borrow_mut().probe_value(b); let i_b = self.unification_table.borrow_mut().probe_value(b);
if a == i_b { if a == i_b {
return Err("Recursive type detected!".to_owned()); return Err("Recursive type is prohibited.".to_owned());
} }
let ty = self.type_arena.borrow().get(i_b.0).unwrap().clone(); let ty = self.type_arena.borrow().get(i_b.0).unwrap().clone();
let ty = ty.borrow(); let ty = ty.borrow();