Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MPR#7937: avoid Unify exception when looking for type declaration #2287

Merged
merged 1 commit into from Mar 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions Changes
Expand Up @@ -38,6 +38,12 @@ Working version
unbound Unix socket. Add support for receiving abstract (Linux) socket paths.
(Tim Cuthbertson, review by Sébastien Hinderer and Jérémie Dimino)

### Bug fixes:

- MPR#7937, GPR#2287: fix uncaught Unify exception when looking for type
declaration
(Florian Angeletti, review by Jacques Garrigue)

OCaml 4.08.0
------------

Expand Down
1 change: 1 addition & 0 deletions testsuite/tests/typing-misc/ocamltests
Expand Up @@ -14,6 +14,7 @@ pr6939-no-flat-float-array.ml
pr7103.ml
pr7228.ml
pr7668_bad.ml
pr7937.ml
printing.ml
records.ml
scope_escape.ml
Expand Down
84 changes: 84 additions & 0 deletions testsuite/tests/typing-misc/pr7937.ml
@@ -0,0 +1,84 @@
(* TEST
* expect
*)

type 'a r = [< `X of int & 'a ] as 'a

let f: 'a. 'a r -> 'a r = fun x -> true;;
[%%expect {|
type 'a r = 'a constraint 'a = [< `X of int & 'a ]
Line 3, characters 35-39:
3 | let f: 'a. 'a r -> 'a r = fun x -> true;;
^^^^
Error: This expression has type bool but an expression was expected of type
([< `X of int & 'a ] as 'a) r
Types for tag `X are incompatible
|}, Principal{|
type 'a r = 'a constraint 'a = [< `X of int & 'a ]
Line 3, characters 30-31:
3 | let f: 'a. 'a r -> 'a r = fun x -> true;;
^
Error: This pattern matches values of type
([< `X of 'b & 'a & 'c & 'd & 'e ] as 'a) r
but a pattern was expected which matches values of type
([< `X of int & 'f ] as 'f) r
Types for tag `X are incompatible
|}]

let g: 'a. 'a r -> 'a r = fun x -> { contents = 0 };;
[%%expect {|
Line 1, characters 35-51:
1 | let g: 'a. 'a r -> 'a r = fun x -> { contents = 0 };;
^^^^^^^^^^^^^^^^
Error: This expression has type int ref
but an expression was expected of type ([< `X of int & 'a ] as 'a) r
Types for tag `X are incompatible
|}, Principal{|
Line 1, characters 30-31:
1 | let g: 'a. 'a r -> 'a r = fun x -> { contents = 0 };;
^
Error: This pattern matches values of type
([< `X of 'b & 'a & 'c & 'd & 'e ] as 'a) r
but a pattern was expected which matches values of type
([< `X of int & 'f ] as 'f) r
Types for tag `X are incompatible
|}]

let h: 'a. 'a r -> _ = function true | false -> ();;
[%%expect {|
Line 1, characters 32-36:
1 | let h: 'a. 'a r -> _ = function true | false -> ();;
^^^^
Error: This pattern matches values of type bool
but a pattern was expected which matches values of type
([< `X of int & 'a ] as 'a) r
Types for tag `X are incompatible
|}, Principal{|
Line 1, characters 32-36:
1 | let h: 'a. 'a r -> _ = function true | false -> ();;
^^^^
Error: This pattern matches values of type bool
but a pattern was expected which matches values of type
([< `X of 'b & 'a & 'c ] as 'a) r
Types for tag `X are incompatible
|}]


let i: 'a. 'a r -> _ = function { contents = 0 } -> ();;
[%%expect {|
Line 1, characters 32-48:
1 | let i: 'a. 'a r -> _ = function { contents = 0 } -> ();;
^^^^^^^^^^^^^^^^
Error: This pattern matches values of type int ref
but a pattern was expected which matches values of type
([< `X of int & 'a ] as 'a) r
Types for tag `X are incompatible
|}, Principal{|
Line 1, characters 32-48:
1 | let i: 'a. 'a r -> _ = function { contents = 0 } -> ();;
^^^^^^^^^^^^^^^^
Error: This pattern matches values of type int ref
but a pattern was expected which matches values of type
([< `X of 'b & 'a & 'c ] as 'a) r
Types for tag `X are incompatible
|}]
7 changes: 5 additions & 2 deletions typing/ctype.ml
Expand Up @@ -1584,7 +1584,10 @@ let expand_head env ty =
let _ = forward_try_expand_once := try_expand_safe


(* Expand until we find a non-abstract type declaration *)
(* Expand until we find a non-abstract type declaration,
use try_expand_safe to avoid raising "Unify _" when
called on recursive types
*)

let rec extract_concrete_typedecl env ty =
let ty = repr ty in
Expand All @@ -1593,7 +1596,7 @@ let rec extract_concrete_typedecl env ty =
let decl = Env.find_type p env in
if decl.type_kind <> Type_abstract then (p, p, decl) else
let ty =
try try_expand_once env ty with Cannot_expand -> raise Not_found
try try_expand_safe env ty with Cannot_expand -> raise Not_found
in
let (_, p', decl) = extract_concrete_typedecl env ty in
(p, p', decl)
Expand Down