Skip to content

Commit

Permalink
fix bugs in the collapse after occur_check
Browse files Browse the repository at this point in the history
During the collapse, there were 2 bugs:
 - one variable out of two were ignore by the collapse
 - everything was collapse to a random variable, and this could break
   invariant that flags must be increasing in the substitution.
  • Loading branch information
FardaleM committed Oct 10, 2024
1 parent 5aa86b5 commit 0cb4618
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 4 deletions.
14 changes: 14 additions & 0 deletions lib/common/Variable.ml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,20 @@ let are_flags_included v1 v2 = Flags.subset v1.flags v2.flags
let merge_flags v1 v2 gen =
gen (Flags.union v1.flags v2.flags)

let rec find_most_general_rec flags v = function
| h :: t ->
let flags_h = get_flags h in
let new_flags = Flags.union flags flags_h in
if Flags.equal new_flags flags_h then find_most_general_rec new_flags (Some h) t
else if Flags.equal new_flags flags then find_most_general_rec new_flags v t
else find_most_general_rec new_flags None t
| [] ->
match v with
| Some v -> Either.Left v
| None -> Either.Right flags

let find_most_general = find_most_general_rec Flags.empty None

module Map = CCMap.Make (struct
type nonrec t = t
let compare = compare
Expand Down
2 changes: 2 additions & 0 deletions lib/common/Variable.mli
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ val are_flags_included : t -> t -> bool
*)
val merge_flags : t -> t -> ( Flags.t -> t) -> t

val find_most_general : t list -> (t, Flags.t) Either.t

module Map : CCMap.S with type key = t
module HMap : CCHashtbl.S with type key = t
module Set : CCSet.S with type elt = t
Expand Down
12 changes: 8 additions & 4 deletions lib/unification/Syntactic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -129,16 +129,20 @@ let rec occur_check env : return =
(Type.tuple (Env.tyenv env) Type.NSet.empty)(*unit*))
l stack
in
collapse stack tl
collapse stack (v::tl)
)
| _ -> Some stack
in
match collapse Stack.empty l with
| None -> FailedOccurCheck env
| Some stack ->
let v = List.hd l in
List.iter (fun u -> Env.add env u (Type.var (Env.tyenv env) v)) (List.tl l);
Env.remove env v;
(match Variable.find_most_general l with
| Either.Right flags ->
let v = Env.gen flags env in
List.iter (fun u -> Env.add env u (Type.var (Env.tyenv env) v)) l
| Left v ->
List.iter (fun u -> Env.add env u (Type.var (Env.tyenv env) v)) l;
Env.remove env v);
let* () = process_stack env stack in
occur_check env

Expand Down
2 changes: 2 additions & 0 deletions test/unit_tests/test_unification.ml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ let pos_tests = [
"'a -> 'b", "'a * 'b" ;
(* Bug non-arrow *)
"((float -> int) * float * int, int -> 'b) t", "('b * int, int -> 'b) t";
(* Bug occur check collapse *)
"'a * 'a -> 'a", "('c * 'd * 'e * 'f * (('c * 'e -> 'a)) * (('d * 'f -> 'b)) -> ('a * 'b))"
]

let neg_tests = [
Expand Down

0 comments on commit 0cb4618

Please sign in to comment.