Improved exhaustiveness warnings for GADTs, with non-deterministic in type_pat
git-svn-id: http://caml.inria.fr/svn/ocaml/branches/gadt-warnings@16133 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02master
parent
82c9bc58a0
commit
c88f3d0634
|
@ -63,15 +63,7 @@ val plus_assoc :
|
||||||
# val smaller : ('a succ, 'b succ) le -> ('a, 'b) le = <fun>
|
# val smaller : ('a succ, 'b succ) le -> ('a, 'b) le = <fun>
|
||||||
# type (_, _) diff = Diff : 'c nat * ('a, 'c, 'b) plus -> ('a, 'b) diff
|
# type (_, _) diff = Diff : 'c nat * ('a, 'c, 'b) plus -> ('a, 'b) diff
|
||||||
# * * * * * * * * * val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = <fun>
|
# * * * * * * * * * val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = <fun>
|
||||||
# Characters 87-243:
|
# val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = <fun>
|
||||||
..match a, b,le with (* warning *)
|
|
||||||
| NZ, m, LeZ _ -> Diff (m, PlusZ m)
|
|
||||||
| NS x, NS y, LeS q ->
|
|
||||||
match diff q x y with Diff (m, p) -> Diff (m, PlusS p)
|
|
||||||
Warning 8: this pattern-matching is not exhaustive.
|
|
||||||
Here is an example of a value that is not matched:
|
|
||||||
(NS _, NZ, _)
|
|
||||||
val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = <fun>
|
|
||||||
# val diff : ('a, 'b) le -> 'b nat -> ('a, 'b) diff = <fun>
|
# val diff : ('a, 'b) le -> 'b nat -> ('a, 'b) diff = <fun>
|
||||||
# type (_, _) filter = Filter : ('m, 'n) le * ('a, 'm) seq -> ('a, 'n) filter
|
# type (_, _) filter = Filter : ('m, 'n) le * ('a, 'm) seq -> ('a, 'n) filter
|
||||||
val leS' : ('m, 'n) le -> ('m, 'n succ) le = <fun>
|
val leS' : ('m, 'n) le -> ('m, 'n succ) le = <fun>
|
||||||
|
|
|
@ -63,15 +63,7 @@ val plus_assoc :
|
||||||
# val smaller : ('a succ, 'b succ) le -> ('a, 'b) le = <fun>
|
# val smaller : ('a succ, 'b succ) le -> ('a, 'b) le = <fun>
|
||||||
# type (_, _) diff = Diff : 'c nat * ('a, 'c, 'b) plus -> ('a, 'b) diff
|
# type (_, _) diff = Diff : 'c nat * ('a, 'c, 'b) plus -> ('a, 'b) diff
|
||||||
# * * * * * * * * * val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = <fun>
|
# * * * * * * * * * val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = <fun>
|
||||||
# Characters 87-243:
|
# val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = <fun>
|
||||||
..match a, b,le with (* warning *)
|
|
||||||
| NZ, m, LeZ _ -> Diff (m, PlusZ m)
|
|
||||||
| NS x, NS y, LeS q ->
|
|
||||||
match diff q x y with Diff (m, p) -> Diff (m, PlusS p)
|
|
||||||
Warning 8: this pattern-matching is not exhaustive.
|
|
||||||
Here is an example of a value that is not matched:
|
|
||||||
(NS _, NZ, _)
|
|
||||||
val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = <fun>
|
|
||||||
# val diff : ('a, 'b) le -> 'b nat -> ('a, 'b) diff = <fun>
|
# val diff : ('a, 'b) le -> 'b nat -> ('a, 'b) diff = <fun>
|
||||||
# type (_, _) filter = Filter : ('m, 'n) le * ('a, 'm) seq -> ('a, 'n) filter
|
# type (_, _) filter = Filter : ('m, 'n) le * ('a, 'm) seq -> ('a, 'n) filter
|
||||||
val leS' : ('m, 'n) le -> ('m, 'n succ) le = <fun>
|
val leS' : ('m, 'n) le -> ('m, 'n succ) le = <fun>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
| Tvar var, tb -> 2
|
| Tvar var, tb -> 2
|
||||||
Warning 8: this pattern-matching is not exhaustive.
|
Warning 8: this pattern-matching is not exhaustive.
|
||||||
Here is an example of a value that is not matched:
|
Here is an example of a value that is not matched:
|
||||||
(Tbool, Tvar _)
|
(Tbool, Tvar Zero)
|
||||||
val f : ('env, 'a) typ -> ('env, 'a) typ -> int = <fun>
|
val f : ('env, 'a) typ -> ('env, 'a) typ -> int = <fun>
|
||||||
# Exception: Match_failure ("//toplevel//", 9, 1).
|
# Exception: Match_failure ("//toplevel//", 9, 1).
|
||||||
#
|
#
|
||||||
|
|
|
@ -13,6 +13,6 @@
|
||||||
| Succ (Succ (Succ (Succ Zero))) -> "4"
|
| Succ (Succ (Succ (Succ Zero))) -> "4"
|
||||||
Warning 8: this pattern-matching is not exhaustive.
|
Warning 8: this pattern-matching is not exhaustive.
|
||||||
Here is an example of a value that is not matched:
|
Here is an example of a value that is not matched:
|
||||||
Succ (Succ (Succ (Succ (Succ _))))
|
Succ (Succ (Succ (Succ (Succ Zero))))
|
||||||
val f : aux -> string = <fun>
|
val f : aux -> string = <fun>
|
||||||
#
|
#
|
||||||
|
|
|
@ -13,6 +13,6 @@
|
||||||
| Succ (Succ (Succ (Succ Zero))) -> "4"
|
| Succ (Succ (Succ (Succ Zero))) -> "4"
|
||||||
Warning 8: this pattern-matching is not exhaustive.
|
Warning 8: this pattern-matching is not exhaustive.
|
||||||
Here is an example of a value that is not matched:
|
Here is an example of a value that is not matched:
|
||||||
Succ (Succ (Succ (Succ (Succ _))))
|
Succ (Succ (Succ (Succ (Succ Zero))))
|
||||||
val f : aux -> string = <fun>
|
val f : aux -> string = <fun>
|
||||||
#
|
#
|
||||||
|
|
|
@ -97,6 +97,52 @@ module PR6862 = struct
|
||||||
class d (Just x) = object method x : int = x end
|
class d (Just x) = object method x : int = x end
|
||||||
end;;
|
end;;
|
||||||
|
|
||||||
|
module Exhaustive2 = struct
|
||||||
|
type _ t = Int : int t
|
||||||
|
let f (x : bool t option) = match x with None -> ()
|
||||||
|
end;;
|
||||||
|
|
||||||
|
module PR6220 = struct
|
||||||
|
type 'a t = I : int t | F : float t
|
||||||
|
let f : int t -> int = function I -> 1
|
||||||
|
let g : int t -> int = function I -> 1 | _ -> 2 (* no warning *)
|
||||||
|
end;;
|
||||||
|
|
||||||
|
module PR6403 = struct
|
||||||
|
type (_, _) eq = Refl : ('a, 'a) eq
|
||||||
|
type empty = { bottom : 'a . 'a }
|
||||||
|
type ('a, 'b) sum = Left of 'a | Right of 'b
|
||||||
|
|
||||||
|
let notequal : ((int, bool) eq, empty) sum -> empty = function
|
||||||
|
| Right empty -> empty
|
||||||
|
end;;
|
||||||
|
|
||||||
|
module PR6437 = struct
|
||||||
|
type ('a, 'b) ctx =
|
||||||
|
| Nil : (unit, unit) ctx
|
||||||
|
| Cons : ('a, 'b) ctx -> ('a * unit, 'b * unit) ctx
|
||||||
|
|
||||||
|
type 'a var =
|
||||||
|
| O : ('a * unit) var
|
||||||
|
| S : 'a var -> ('a * unit) var
|
||||||
|
|
||||||
|
let rec f : type g1 g2. (g1, g2) ctx * g1 var -> g2 var = function
|
||||||
|
| Cons g, O -> O
|
||||||
|
| Cons g, S n -> S (f (g, n))
|
||||||
|
(*| Nil, _ -> (assert false) *) (* warns, but shouldn't *)
|
||||||
|
end;;
|
||||||
|
|
||||||
|
module PR6801 = struct
|
||||||
|
type _ value =
|
||||||
|
| String : string -> string value
|
||||||
|
| Float : float -> float value
|
||||||
|
| Any
|
||||||
|
|
||||||
|
let print_string_value (x : string value) =
|
||||||
|
match x with
|
||||||
|
| String s -> print_endline s (* warn : Any *)
|
||||||
|
end;;
|
||||||
|
|
||||||
module Existential_escape =
|
module Existential_escape =
|
||||||
struct
|
struct
|
||||||
type _ t = C : int -> int t
|
type _ t = C : int -> int t
|
||||||
|
@ -114,7 +160,7 @@ module Rectype =
|
||||||
;;
|
;;
|
||||||
|
|
||||||
module Or_patterns =
|
module Or_patterns =
|
||||||
struct
|
struct
|
||||||
type _ t =
|
type _ t =
|
||||||
| IntLit : int -> int t
|
| IntLit : int -> int t
|
||||||
| BoolLit : bool -> bool t
|
| BoolLit : bool -> bool t
|
||||||
|
|
|
@ -65,6 +65,43 @@ module PR6862 :
|
||||||
type _ opt = Just : 'a -> 'a opt | Nothing : 'a opt
|
type _ opt = Just : 'a -> 'a opt | Nothing : 'a opt
|
||||||
class d : int opt -> object method x : int end
|
class d : int opt -> object method x : int end
|
||||||
end
|
end
|
||||||
|
# module Exhaustive2 :
|
||||||
|
sig type _ t = Int : int t val f : bool t option -> unit end
|
||||||
|
# module PR6220 :
|
||||||
|
sig
|
||||||
|
type 'a t = I : int t | F : float t
|
||||||
|
val f : int t -> int
|
||||||
|
val g : int t -> int
|
||||||
|
end
|
||||||
|
# module PR6403 :
|
||||||
|
sig
|
||||||
|
type (_, _) eq = Refl : ('a, 'a) eq
|
||||||
|
type empty = { bottom : 'a. 'a; }
|
||||||
|
type ('a, 'b) sum = Left of 'a | Right of 'b
|
||||||
|
val notequal : ((int, bool) eq, empty) sum -> empty
|
||||||
|
end
|
||||||
|
# module PR6437 :
|
||||||
|
sig
|
||||||
|
type ('a, 'b) ctx =
|
||||||
|
Nil : (unit, unit) ctx
|
||||||
|
| Cons : ('a, 'b) ctx -> ('a * unit, 'b * unit) ctx
|
||||||
|
type 'a var = O : ('a * unit) var | S : 'a var -> ('a * unit) var
|
||||||
|
val f : ('g1, 'g2) ctx * 'g1 var -> 'g2 var
|
||||||
|
end
|
||||||
|
# Characters 175-221:
|
||||||
|
....match x with
|
||||||
|
| String s -> print_endline s.................
|
||||||
|
Warning 8: this pattern-matching is not exhaustive.
|
||||||
|
Here is an example of a value that is not matched:
|
||||||
|
Any
|
||||||
|
module PR6801 :
|
||||||
|
sig
|
||||||
|
type _ value =
|
||||||
|
String : string -> string value
|
||||||
|
| Float : float -> float value
|
||||||
|
| Any
|
||||||
|
val print_string_value : string value -> unit
|
||||||
|
end
|
||||||
# Characters 118-119:
|
# Characters 118-119:
|
||||||
let eval (D x) = x
|
let eval (D x) = x
|
||||||
^
|
^
|
||||||
|
@ -73,7 +110,7 @@ Error: This expression has type a#2 t but an expression was expected of type
|
||||||
The type constructor a#2 would escape its scope
|
The type constructor a#2 would escape its scope
|
||||||
# module Rectype :
|
# module Rectype :
|
||||||
sig type (_, _) t = C : ('a, 'a) t val f : ('s, 's * 's) t -> unit end
|
sig type (_, _) t = C : ('a, 'a) t val f : ('s, 's * 's) t -> unit end
|
||||||
# Characters 178-186:
|
# Characters 180-188:
|
||||||
| (IntLit _ | BoolLit _) -> ()
|
| (IntLit _ | BoolLit _) -> ()
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
Error: This pattern matches values of type int t
|
Error: This pattern matches values of type int t
|
||||||
|
@ -265,7 +302,7 @@ val f : 'a ty -> 'a t -> int = <fun>
|
||||||
| TA, D z -> z
|
| TA, D z -> z
|
||||||
Warning 8: this pattern-matching is not exhaustive.
|
Warning 8: this pattern-matching is not exhaustive.
|
||||||
Here is an example of a value that is not matched:
|
Here is an example of a value that is not matched:
|
||||||
(TE TC, D [| |])
|
(TE TC, D [| 0. |])
|
||||||
val f : 'a ty -> 'a t -> int = <fun>
|
val f : 'a ty -> 'a t -> int = <fun>
|
||||||
# Characters 147-154:
|
# Characters 147-154:
|
||||||
| D [|1.0|], TE TC -> 14
|
| D [|1.0|], TE TC -> 14
|
||||||
|
@ -287,7 +324,7 @@ Error: This pattern matches values of type 'a array
|
||||||
| {left=TA; right=D z} -> z
|
| {left=TA; right=D z} -> z
|
||||||
Warning 8: this pattern-matching is not exhaustive.
|
Warning 8: this pattern-matching is not exhaustive.
|
||||||
Here is an example of a value that is not matched:
|
Here is an example of a value that is not matched:
|
||||||
{left=TE TC; right=D [| |]}
|
{left=TE TC; right=D [| 0. |]}
|
||||||
type ('a, 'b) pair = { left : 'a; right : 'b; }
|
type ('a, 'b) pair = { left : 'a; right : 'b; }
|
||||||
val f : 'a ty -> 'a t -> int = <fun>
|
val f : 'a ty -> 'a t -> int = <fun>
|
||||||
# module M : sig type 'a t val eq : ('a t, 'b t) eq end
|
# module M : sig type 'a t val eq : ('a t, 'b t) eq end
|
||||||
|
@ -309,14 +346,14 @@ type _ int_bar = IB_constr : < bar : int; .. > int_bar
|
||||||
^
|
^
|
||||||
Error: This expression has type t = < foo : int; .. >
|
Error: This expression has type t = < foo : int; .. >
|
||||||
but an expression was expected of type < foo : int >
|
but an expression was expected of type < foo : int >
|
||||||
Type ex#17 = < bar : int; .. > is not compatible with type < >
|
Type ex#25 = < bar : int; .. > is not compatible with type < >
|
||||||
The second object type has no method bar
|
The second object type has no method bar
|
||||||
# Characters 98-99:
|
# Characters 98-99:
|
||||||
(x:<foo:int;bar:int>)
|
(x:<foo:int;bar:int>)
|
||||||
^
|
^
|
||||||
Error: This expression has type t = < foo : int; .. >
|
Error: This expression has type t = < foo : int; .. >
|
||||||
but an expression was expected of type < bar : int; foo : int >
|
but an expression was expected of type < bar : int; foo : int >
|
||||||
Type ex#19 = < bar : int; .. > is not compatible with type
|
Type ex#27 = < bar : int; .. > is not compatible with type
|
||||||
< bar : int >
|
< bar : int >
|
||||||
The first object type has an abstract row, it cannot be closed
|
The first object type has an abstract row, it cannot be closed
|
||||||
# Characters 98-99:
|
# Characters 98-99:
|
||||||
|
@ -324,7 +361,7 @@ Error: This expression has type t = < foo : int; .. >
|
||||||
^
|
^
|
||||||
Error: This expression has type < bar : int; foo : int; .. >
|
Error: This expression has type < bar : int; foo : int; .. >
|
||||||
but an expression was expected of type 'a
|
but an expression was expected of type 'a
|
||||||
The type constructor ex#22 would escape its scope
|
The type constructor ex#30 would escape its scope
|
||||||
# val g : 'a -> 'a int_foo -> 'a int_bar -> 'a = <fun>
|
# val g : 'a -> 'a int_foo -> 'a int_bar -> 'a = <fun>
|
||||||
# val g : 'a -> 'a int_foo -> 'a int_bar -> 'a * int * int = <fun>
|
# val g : 'a -> 'a int_foo -> 'a int_bar -> 'a * int * int = <fun>
|
||||||
# type 'a ty = Int : int -> int ty
|
# type 'a ty = Int : int -> int ty
|
||||||
|
|
|
@ -65,6 +65,43 @@ module PR6862 :
|
||||||
type _ opt = Just : 'a -> 'a opt | Nothing : 'a opt
|
type _ opt = Just : 'a -> 'a opt | Nothing : 'a opt
|
||||||
class d : int opt -> object method x : int end
|
class d : int opt -> object method x : int end
|
||||||
end
|
end
|
||||||
|
# module Exhaustive2 :
|
||||||
|
sig type _ t = Int : int t val f : bool t option -> unit end
|
||||||
|
# module PR6220 :
|
||||||
|
sig
|
||||||
|
type 'a t = I : int t | F : float t
|
||||||
|
val f : int t -> int
|
||||||
|
val g : int t -> int
|
||||||
|
end
|
||||||
|
# module PR6403 :
|
||||||
|
sig
|
||||||
|
type (_, _) eq = Refl : ('a, 'a) eq
|
||||||
|
type empty = { bottom : 'a. 'a; }
|
||||||
|
type ('a, 'b) sum = Left of 'a | Right of 'b
|
||||||
|
val notequal : ((int, bool) eq, empty) sum -> empty
|
||||||
|
end
|
||||||
|
# module PR6437 :
|
||||||
|
sig
|
||||||
|
type ('a, 'b) ctx =
|
||||||
|
Nil : (unit, unit) ctx
|
||||||
|
| Cons : ('a, 'b) ctx -> ('a * unit, 'b * unit) ctx
|
||||||
|
type 'a var = O : ('a * unit) var | S : 'a var -> ('a * unit) var
|
||||||
|
val f : ('g1, 'g2) ctx * 'g1 var -> 'g2 var
|
||||||
|
end
|
||||||
|
# Characters 175-221:
|
||||||
|
....match x with
|
||||||
|
| String s -> print_endline s.................
|
||||||
|
Warning 8: this pattern-matching is not exhaustive.
|
||||||
|
Here is an example of a value that is not matched:
|
||||||
|
Any
|
||||||
|
module PR6801 :
|
||||||
|
sig
|
||||||
|
type _ value =
|
||||||
|
String : string -> string value
|
||||||
|
| Float : float -> float value
|
||||||
|
| Any
|
||||||
|
val print_string_value : string value -> unit
|
||||||
|
end
|
||||||
# Characters 118-119:
|
# Characters 118-119:
|
||||||
let eval (D x) = x
|
let eval (D x) = x
|
||||||
^
|
^
|
||||||
|
@ -73,7 +110,7 @@ Error: This expression has type a#2 t but an expression was expected of type
|
||||||
The type constructor a#2 would escape its scope
|
The type constructor a#2 would escape its scope
|
||||||
# module Rectype :
|
# module Rectype :
|
||||||
sig type (_, _) t = C : ('a, 'a) t val f : ('s, 's * 's) t -> unit end
|
sig type (_, _) t = C : ('a, 'a) t val f : ('s, 's * 's) t -> unit end
|
||||||
# Characters 178-186:
|
# Characters 180-188:
|
||||||
| (IntLit _ | BoolLit _) -> ()
|
| (IntLit _ | BoolLit _) -> ()
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
Error: This pattern matches values of type int t
|
Error: This pattern matches values of type int t
|
||||||
|
@ -252,7 +289,7 @@ val f : 'a ty -> 'a t -> int = <fun>
|
||||||
| TA, D z -> z
|
| TA, D z -> z
|
||||||
Warning 8: this pattern-matching is not exhaustive.
|
Warning 8: this pattern-matching is not exhaustive.
|
||||||
Here is an example of a value that is not matched:
|
Here is an example of a value that is not matched:
|
||||||
(TE TC, D [| |])
|
(TE TC, D [| 0. |])
|
||||||
val f : 'a ty -> 'a t -> int = <fun>
|
val f : 'a ty -> 'a t -> int = <fun>
|
||||||
# Characters 147-154:
|
# Characters 147-154:
|
||||||
| D [|1.0|], TE TC -> 14
|
| D [|1.0|], TE TC -> 14
|
||||||
|
@ -274,7 +311,7 @@ Error: This pattern matches values of type 'a array
|
||||||
| {left=TA; right=D z} -> z
|
| {left=TA; right=D z} -> z
|
||||||
Warning 8: this pattern-matching is not exhaustive.
|
Warning 8: this pattern-matching is not exhaustive.
|
||||||
Here is an example of a value that is not matched:
|
Here is an example of a value that is not matched:
|
||||||
{left=TE TC; right=D [| |]}
|
{left=TE TC; right=D [| 0. |]}
|
||||||
type ('a, 'b) pair = { left : 'a; right : 'b; }
|
type ('a, 'b) pair = { left : 'a; right : 'b; }
|
||||||
val f : 'a ty -> 'a t -> int = <fun>
|
val f : 'a ty -> 'a t -> int = <fun>
|
||||||
# module M : sig type 'a t val eq : ('a t, 'b t) eq end
|
# module M : sig type 'a t val eq : ('a t, 'b t) eq end
|
||||||
|
@ -296,14 +333,14 @@ type _ int_bar = IB_constr : < bar : int; .. > int_bar
|
||||||
^
|
^
|
||||||
Error: This expression has type t = < foo : int; .. >
|
Error: This expression has type t = < foo : int; .. >
|
||||||
but an expression was expected of type < foo : int >
|
but an expression was expected of type < foo : int >
|
||||||
Type ex#17 = < bar : int; .. > is not compatible with type < >
|
Type ex#25 = < bar : int; .. > is not compatible with type < >
|
||||||
The second object type has no method bar
|
The second object type has no method bar
|
||||||
# Characters 98-99:
|
# Characters 98-99:
|
||||||
(x:<foo:int;bar:int>)
|
(x:<foo:int;bar:int>)
|
||||||
^
|
^
|
||||||
Error: This expression has type t = < foo : int; .. >
|
Error: This expression has type t = < foo : int; .. >
|
||||||
but an expression was expected of type < bar : int; foo : int >
|
but an expression was expected of type < bar : int; foo : int >
|
||||||
Type ex#19 = < bar : int; .. > is not compatible with type
|
Type ex#27 = < bar : int; .. > is not compatible with type
|
||||||
< bar : int >
|
< bar : int >
|
||||||
The first object type has an abstract row, it cannot be closed
|
The first object type has an abstract row, it cannot be closed
|
||||||
# Characters 98-99:
|
# Characters 98-99:
|
||||||
|
@ -311,7 +348,7 @@ Error: This expression has type t = < foo : int; .. >
|
||||||
^
|
^
|
||||||
Error: This expression has type < bar : int; foo : int; .. >
|
Error: This expression has type < bar : int; foo : int; .. >
|
||||||
but an expression was expected of type 'a
|
but an expression was expected of type 'a
|
||||||
The type constructor ex#22 would escape its scope
|
The type constructor ex#30 would escape its scope
|
||||||
# val g : 'a -> 'a int_foo -> 'a int_bar -> 'a = <fun>
|
# val g : 'a -> 'a int_foo -> 'a int_bar -> 'a = <fun>
|
||||||
# val g : 'a -> 'a int_foo -> 'a int_bar -> 'a * int * int = <fun>
|
# val g : 'a -> 'a int_foo -> 'a int_bar -> 'a * int * int = <fun>
|
||||||
# type 'a ty = Int : int -> int ty
|
# type 'a ty = Int : int -> int ty
|
||||||
|
|
|
@ -116,6 +116,20 @@ let nongen_level = ref 0
|
||||||
let global_level = ref 1
|
let global_level = ref 1
|
||||||
let saved_level = ref []
|
let saved_level = ref []
|
||||||
|
|
||||||
|
type levels =
|
||||||
|
{ current_level: int; nongen_level: int; global_level: int;
|
||||||
|
saved_level: (int * int) list; }
|
||||||
|
let save_levels () =
|
||||||
|
{ current_level = !current_level;
|
||||||
|
nongen_level = !nongen_level;
|
||||||
|
global_level = !global_level;
|
||||||
|
saved_level = !saved_level }
|
||||||
|
let set_levels l =
|
||||||
|
current_level := l.current_level;
|
||||||
|
nongen_level := l.nongen_level;
|
||||||
|
global_level := l.global_level;
|
||||||
|
saved_level := l.saved_level
|
||||||
|
|
||||||
let get_current_level () = !current_level
|
let get_current_level () = !current_level
|
||||||
let init_def level = current_level := level; nongen_level := level
|
let init_def level = current_level := level; nongen_level := level
|
||||||
let begin_def () =
|
let begin_def () =
|
||||||
|
|
|
@ -37,6 +37,11 @@ val reset_global_level: unit -> unit
|
||||||
val increase_global_level: unit -> int
|
val increase_global_level: unit -> int
|
||||||
val restore_global_level: int -> unit
|
val restore_global_level: int -> unit
|
||||||
(* This pair of functions is only used in Typetexp *)
|
(* This pair of functions is only used in Typetexp *)
|
||||||
|
type levels =
|
||||||
|
{ current_level: int; nongen_level: int; global_level: int;
|
||||||
|
saved_level: (int * int) list; }
|
||||||
|
val save_levels: unit -> levels
|
||||||
|
val set_levels: levels -> unit
|
||||||
|
|
||||||
val newty: type_desc -> type_expr
|
val newty: type_desc -> type_expr
|
||||||
val newvar: ?name:string -> unit -> type_expr
|
val newvar: ?name:string -> unit -> type_expr
|
||||||
|
|
|
@ -621,18 +621,10 @@ let clean_env env =
|
||||||
in
|
in
|
||||||
loop env
|
loop env
|
||||||
|
|
||||||
let full_match ignore_generalized closing env = match env with
|
let full_match closing env = match env with
|
||||||
| ({pat_desc = Tpat_construct(_,c,_);pat_type=typ},_) :: _ ->
|
| ({pat_desc = Tpat_construct(_,c,_);pat_type=typ},_) :: _ ->
|
||||||
if c.cstr_consts < 0 then false (* extensions *)
|
if c.cstr_consts < 0 then false (* extensions *)
|
||||||
else
|
else List.length env = c.cstr_consts + c.cstr_nonconsts
|
||||||
if ignore_generalized then
|
|
||||||
(* remove generalized constructors;
|
|
||||||
those cases will be handled separately *)
|
|
||||||
let env = clean_env env in
|
|
||||||
List.length env = c.cstr_normal
|
|
||||||
else
|
|
||||||
List.length env = c.cstr_consts + c.cstr_nonconsts
|
|
||||||
|
|
||||||
| ({pat_desc = Tpat_variant _} as p,_) :: _ ->
|
| ({pat_desc = Tpat_variant _} as p,_) :: _ ->
|
||||||
let fields =
|
let fields =
|
||||||
List.map
|
List.map
|
||||||
|
@ -666,11 +658,6 @@ let full_match ignore_generalized closing env = match env with
|
||||||
| ({pat_desc = Tpat_lazy(_)},_) :: _ -> true
|
| ({pat_desc = Tpat_lazy(_)},_) :: _ -> true
|
||||||
| _ -> fatal_error "Parmatch.full_match"
|
| _ -> fatal_error "Parmatch.full_match"
|
||||||
|
|
||||||
let full_match_gadt env = match env with
|
|
||||||
| ({pat_desc = Tpat_construct(_,c,_);pat_type=typ},_) :: _ ->
|
|
||||||
List.length env = c.cstr_consts + c.cstr_nonconsts
|
|
||||||
| _ -> true
|
|
||||||
|
|
||||||
let extendable_match env = match env with
|
let extendable_match env = match env with
|
||||||
| ({pat_desc=Tpat_construct(_,{cstr_tag=(Cstr_constant _|Cstr_block _)},_)}
|
| ({pat_desc=Tpat_construct(_,{cstr_tag=(Cstr_constant _|Cstr_block _)},_)}
|
||||||
as p,_) :: _ ->
|
as p,_) :: _ ->
|
||||||
|
@ -715,19 +702,34 @@ let complete_tags nconsts nconstrs tags =
|
||||||
|
|
||||||
(* build a pattern from a constructor list *)
|
(* build a pattern from a constructor list *)
|
||||||
let pat_of_constr ex_pat cstr =
|
let pat_of_constr ex_pat cstr =
|
||||||
{ex_pat with pat_desc =
|
{ex_pat with pat_desc =
|
||||||
Tpat_construct (mknoloc (Longident.Lident "?pat_of_constr?"),
|
Tpat_construct (mknoloc (Longident.Lident "?pat_of_constr?"),
|
||||||
cstr,omegas cstr.cstr_arity)}
|
cstr, omegas cstr.cstr_arity)}
|
||||||
|
|
||||||
let rec pat_of_constrs ex_pat = function
|
let rec orify_many = function
|
||||||
| [] -> raise Empty
|
| [] -> assert false
|
||||||
| [cstr] -> pat_of_constr ex_pat cstr
|
| [x] -> x
|
||||||
| cstr::rem ->
|
| x :: xs ->
|
||||||
{ex_pat with
|
make_pat (Tpat_or (x, orify_many xs, None)) x.pat_type x.pat_env
|
||||||
pat_desc=
|
|
||||||
Tpat_or
|
let pat_of_constrs ex_pat cstrs =
|
||||||
(pat_of_constr ex_pat cstr,
|
if cstrs = [] then raise Empty else
|
||||||
pat_of_constrs ex_pat rem, None)}
|
orify_many (List.map (pat_of_constr ex_pat) cstrs)
|
||||||
|
|
||||||
|
let pats_of_type env ty =
|
||||||
|
let ty' = Ctype.expand_head env ty in
|
||||||
|
match ty'.desc with
|
||||||
|
| Tconstr (path, _, _) ->
|
||||||
|
begin match Env.find_type path env with
|
||||||
|
| {type_kind = Type_variant cl}
|
||||||
|
when List.for_all (fun cd -> cd.Types.cd_res <> None) cl ->
|
||||||
|
let cstrs = fst (Env.find_type_descrs path env) in
|
||||||
|
List.map
|
||||||
|
(pat_of_constr {omega with pat_type=ty; pat_env=env})
|
||||||
|
cstrs
|
||||||
|
| _ -> [omega]
|
||||||
|
end
|
||||||
|
| _ -> [omega]
|
||||||
|
|
||||||
let rec get_variant_constructors env ty =
|
let rec get_variant_constructors env ty =
|
||||||
match (Ctype.repr ty).desc with
|
match (Ctype.repr ty).desc with
|
||||||
|
@ -756,11 +758,12 @@ let complete_constrs p all_tags =
|
||||||
| Tpat_construct (_,c,_) ->
|
| Tpat_construct (_,c,_) ->
|
||||||
let not_tags = complete_tags c.cstr_consts c.cstr_nonconsts all_tags in
|
let not_tags = complete_tags c.cstr_consts c.cstr_nonconsts all_tags in
|
||||||
let constrs = get_variant_constructors p.pat_env c.cstr_res in
|
let constrs = get_variant_constructors p.pat_env c.cstr_res in
|
||||||
map_filter
|
let others =
|
||||||
(fun cnstr ->
|
List.filter (fun cnstr -> List.mem cnstr.cstr_tag not_tags) constrs in
|
||||||
if List.mem cnstr.cstr_tag not_tags then Some cnstr else None)
|
let const, nonconst =
|
||||||
constrs
|
List.partition (fun cnstr -> cnstr.cstr_arity = 0) others in
|
||||||
| _ -> fatal_error "Parmatch.complete_constr"
|
const @ nonconst
|
||||||
|
| _ -> fatal_error "Parmatch.complete_constrs"
|
||||||
|
|
||||||
|
|
||||||
(* Auxiliary for build_other *)
|
(* Auxiliary for build_other *)
|
||||||
|
@ -778,7 +781,7 @@ let build_other_constant proj make first next p env =
|
||||||
in the first column of env
|
in the first column of env
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let build_other ext env = match env with
|
let build_other ext env = match env with
|
||||||
| ({pat_desc = Tpat_construct (lid,
|
| ({pat_desc = Tpat_construct (lid,
|
||||||
({cstr_tag=Cstr_extension _} as c),_)},_) :: _ ->
|
({cstr_tag=Cstr_extension _} as c),_)},_) :: _ ->
|
||||||
let c = {c with cstr_name = "*extension*"} in
|
let c = {c with cstr_name = "*extension*"} in
|
||||||
|
@ -902,20 +905,6 @@ let build_other ext env = match env with
|
||||||
| [] -> omega
|
| [] -> omega
|
||||||
| _ -> omega
|
| _ -> omega
|
||||||
|
|
||||||
let build_other_gadt ext env =
|
|
||||||
match env with
|
|
||||||
| ({pat_desc = Tpat_construct _} as p,_) :: _ ->
|
|
||||||
let get_tag = function
|
|
||||||
| {pat_desc = Tpat_construct (_,c,_)} -> c.cstr_tag
|
|
||||||
| _ -> fatal_error "Parmatch.get_tag" in
|
|
||||||
let all_tags = List.map (fun (p,_) -> get_tag p) env in
|
|
||||||
let cnstrs = complete_constrs p all_tags in
|
|
||||||
let pats = List.map (pat_of_constr p) cnstrs in
|
|
||||||
(* List.iter (Format.eprintf "%a@." top_pretty) pats;
|
|
||||||
Format.eprintf "@.@."; *)
|
|
||||||
pats
|
|
||||||
| _ -> assert false
|
|
||||||
|
|
||||||
(*
|
(*
|
||||||
Core function :
|
Core function :
|
||||||
Is the last row of pattern matrix pss + qs satisfiable ?
|
Is the last row of pattern matrix pss + qs satisfiable ?
|
||||||
|
@ -956,7 +945,7 @@ let rec satisfiable pss qs = match pss with
|
||||||
(* first column of pss is made of variables only *)
|
(* first column of pss is made of variables only *)
|
||||||
| [] -> satisfiable (filter_extra pss) qs
|
| [] -> satisfiable (filter_extra pss) qs
|
||||||
| constrs ->
|
| constrs ->
|
||||||
if full_match false false constrs then
|
if full_match false constrs then
|
||||||
List.exists
|
List.exists
|
||||||
(fun (p,pss) ->
|
(fun (p,pss) ->
|
||||||
not (is_absent_pat p) &&
|
not (is_absent_pat p) &&
|
||||||
|
@ -981,15 +970,6 @@ type 'a result =
|
||||||
| Rnone (* No matching value *)
|
| Rnone (* No matching value *)
|
||||||
| Rsome of 'a (* This matching value *)
|
| Rsome of 'a (* This matching value *)
|
||||||
|
|
||||||
let rec orify_many =
|
|
||||||
let orify x y =
|
|
||||||
make_pat (Tpat_or (x, y, None)) x.pat_type x.pat_env
|
|
||||||
in
|
|
||||||
function
|
|
||||||
| [] -> assert false
|
|
||||||
| [x] -> x
|
|
||||||
| x :: xs -> orify x (orify_many xs)
|
|
||||||
|
|
||||||
let rec try_many f = function
|
let rec try_many f = function
|
||||||
| [] -> Rnone
|
| [] -> Rnone
|
||||||
| (p,pss)::rest ->
|
| (p,pss)::rest ->
|
||||||
|
@ -1008,6 +988,7 @@ let rec try_many_gadt f = function
|
||||||
| (p,pss)::rest ->
|
| (p,pss)::rest ->
|
||||||
rappend (f (p, pss)) (try_many_gadt f rest)
|
rappend (f (p, pss)) (try_many_gadt f rest)
|
||||||
|
|
||||||
|
(*
|
||||||
let rec exhaust ext pss n = match pss with
|
let rec exhaust ext pss n = match pss with
|
||||||
| [] -> Rsome (omegas n)
|
| [] -> Rsome (omegas n)
|
||||||
| []::_ -> Rnone
|
| []::_ -> Rnone
|
||||||
|
@ -1068,7 +1049,7 @@ let combinations f lst lst' =
|
||||||
| x :: xs -> iter2 x lst' @ iter xs
|
| x :: xs -> iter2 x lst' @ iter xs
|
||||||
in
|
in
|
||||||
iter lst
|
iter lst
|
||||||
|
*)
|
||||||
(*
|
(*
|
||||||
let print_pat pat =
|
let print_pat pat =
|
||||||
let rec string_of_pat pat =
|
let rec string_of_pat pat =
|
||||||
|
@ -1119,7 +1100,7 @@ let rec exhaust_gadt (ext:Path.t option) pss n = match pss with
|
||||||
| r -> r in
|
| r -> r in
|
||||||
let before = try_many_gadt try_non_omega constrs in
|
let before = try_many_gadt try_non_omega constrs in
|
||||||
if
|
if
|
||||||
full_match_gadt constrs && not (should_extend ext constrs)
|
full_match false constrs && not (should_extend ext constrs)
|
||||||
then
|
then
|
||||||
before
|
before
|
||||||
else
|
else
|
||||||
|
@ -1136,13 +1117,8 @@ let rec exhaust_gadt (ext:Path.t option) pss n = match pss with
|
||||||
| Rnone -> before
|
| Rnone -> before
|
||||||
| Rsome r ->
|
| Rsome r ->
|
||||||
try
|
try
|
||||||
let missing_trailing = build_other_gadt ext constrs in
|
let p = build_other ext constrs in
|
||||||
let dug =
|
let dug = List.map (fun tail -> p :: tail) r in
|
||||||
combinations
|
|
||||||
(fun head tail -> head :: tail)
|
|
||||||
missing_trailing
|
|
||||||
r
|
|
||||||
in
|
|
||||||
match before with
|
match before with
|
||||||
| Rnone -> Rsome dug
|
| Rnone -> Rsome dug
|
||||||
| Rsome x -> Rsome (x @ dug)
|
| Rsome x -> Rsome (x @ dug)
|
||||||
|
@ -1193,12 +1169,12 @@ let rec pressure_variants tdefs = function
|
||||||
try_non_omega rem && ok
|
try_non_omega rem && ok
|
||||||
| [] -> true
|
| [] -> true
|
||||||
in
|
in
|
||||||
if full_match true (tdefs=None) constrs then
|
if full_match (tdefs=None) constrs then
|
||||||
try_non_omega constrs
|
try_non_omega constrs
|
||||||
else if tdefs = None then
|
else if tdefs = None then
|
||||||
pressure_variants None (filter_extra pss)
|
pressure_variants None (filter_extra pss)
|
||||||
else
|
else
|
||||||
let full = full_match true true constrs in
|
let full = full_match true constrs in
|
||||||
let ok =
|
let ok =
|
||||||
if full then try_non_omega constrs
|
if full then try_non_omega constrs
|
||||||
else try_non_omega (filter_all q0 (mark_partial pss))
|
else try_non_omega (filter_all q0 (mark_partial pss))
|
||||||
|
@ -1662,119 +1638,71 @@ let check_partial_all v casel =
|
||||||
(* Exhaustiveness check *)
|
(* Exhaustiveness check *)
|
||||||
(************************)
|
(************************)
|
||||||
|
|
||||||
|
|
||||||
let rec get_first f =
|
|
||||||
function
|
|
||||||
| [] -> None
|
|
||||||
| x :: xs ->
|
|
||||||
match f x with
|
|
||||||
| None -> get_first f xs
|
|
||||||
| x -> x
|
|
||||||
|
|
||||||
|
|
||||||
(* conversion from Typedtree.pattern to Parsetree.pattern list *)
|
(* conversion from Typedtree.pattern to Parsetree.pattern list *)
|
||||||
module Conv = struct
|
module Conv = struct
|
||||||
open Parsetree
|
open Parsetree
|
||||||
let mkpat desc = Ast_helper.Pat.mk desc
|
let mkpat desc = Ast_helper.Pat.mk desc
|
||||||
|
|
||||||
let rec select : 'a list list -> 'a list list =
|
|
||||||
function
|
|
||||||
| xs :: [] -> List.map (fun y -> [y]) xs
|
|
||||||
| (x::xs)::ys ->
|
|
||||||
List.map
|
|
||||||
(fun lst -> x :: lst)
|
|
||||||
(select ys)
|
|
||||||
@
|
|
||||||
select (xs::ys)
|
|
||||||
| _ -> []
|
|
||||||
|
|
||||||
let name_counter = ref 0
|
let name_counter = ref 0
|
||||||
let fresh name =
|
let fresh name =
|
||||||
let current = !name_counter in
|
let current = !name_counter in
|
||||||
name_counter := !name_counter + 1;
|
name_counter := !name_counter + 1;
|
||||||
"#$" ^ name ^ string_of_int current
|
"#$" ^ name ^ string_of_int current
|
||||||
|
|
||||||
let conv (typed: Typedtree.pattern) :
|
let conv typed =
|
||||||
Parsetree.pattern list *
|
let constrs = Hashtbl.create 7 in
|
||||||
(string, Types.constructor_description) Hashtbl.t *
|
let labels = Hashtbl.create 7 in
|
||||||
(string, Types.label_description) Hashtbl.t
|
|
||||||
=
|
|
||||||
let constrs = Hashtbl.create 0 in
|
|
||||||
let labels = Hashtbl.create 0 in
|
|
||||||
let rec loop pat =
|
let rec loop pat =
|
||||||
match pat.pat_desc with
|
match pat.pat_desc with
|
||||||
Tpat_or (a,b,_) ->
|
Tpat_or (pa,pb,_) ->
|
||||||
loop a @ loop b
|
mkpat (Ppat_or (loop pa, loop pb))
|
||||||
| Tpat_any | Tpat_constant _ | Tpat_var _ ->
|
| Tpat_any
|
||||||
[mkpat Ppat_any]
|
| Tpat_var _ ->
|
||||||
|
mkpat Ppat_any
|
||||||
|
| Tpat_constant c ->
|
||||||
|
mkpat (Ppat_constant c)
|
||||||
| Tpat_alias (p,_,_) -> loop p
|
| Tpat_alias (p,_,_) -> loop p
|
||||||
| Tpat_tuple lst ->
|
| Tpat_tuple lst ->
|
||||||
let results = select (List.map loop lst) in
|
mkpat (Ppat_tuple (List.map loop lst))
|
||||||
List.map
|
| Tpat_construct (cstr_lid, cstr, lst) ->
|
||||||
(fun lst -> mkpat (Ppat_tuple lst))
|
|
||||||
results
|
|
||||||
| Tpat_construct (cstr_lid, cstr,lst) ->
|
|
||||||
let id = fresh cstr.cstr_name in
|
let id = fresh cstr.cstr_name in
|
||||||
let lid = { cstr_lid with txt = Longident.Lident id } in
|
let lid = { cstr_lid with txt = Longident.Lident id } in
|
||||||
Hashtbl.add constrs id cstr;
|
Hashtbl.add constrs id cstr;
|
||||||
let results = select (List.map loop lst) in
|
let arg =
|
||||||
begin match lst with
|
match List.map loop lst with
|
||||||
[] ->
|
| [] -> None
|
||||||
[mkpat (Ppat_construct(lid, None))]
|
| [p] -> Some p
|
||||||
| _ ->
|
| lst -> Some (mkpat (Ppat_tuple lst))
|
||||||
List.map
|
|
||||||
(fun lst ->
|
|
||||||
let arg =
|
|
||||||
match lst with
|
|
||||||
[] -> assert false
|
|
||||||
| [x] -> Some x
|
|
||||||
| _ -> Some (mkpat (Ppat_tuple lst))
|
|
||||||
in
|
|
||||||
mkpat (Ppat_construct(lid, arg)))
|
|
||||||
results
|
|
||||||
end
|
|
||||||
| Tpat_variant(label,p_opt,row_desc) ->
|
|
||||||
begin match p_opt with
|
|
||||||
| None ->
|
|
||||||
[mkpat (Ppat_variant(label, None))]
|
|
||||||
| Some p ->
|
|
||||||
let results = loop p in
|
|
||||||
List.map
|
|
||||||
(fun p ->
|
|
||||||
mkpat (Ppat_variant(label, Some p)))
|
|
||||||
results
|
|
||||||
end
|
|
||||||
| Tpat_record (subpatterns, _closed_flag) ->
|
|
||||||
let pats =
|
|
||||||
select
|
|
||||||
(List.map (fun (_,_,x) -> loop x) subpatterns)
|
|
||||||
in
|
in
|
||||||
let label_idents =
|
mkpat (Ppat_construct(lid, arg))
|
||||||
List.map
|
| Tpat_variant(label,p_opt,row_desc) ->
|
||||||
(fun (_,lbl,_) ->
|
let arg = Misc.may_map loop p_opt in
|
||||||
|
mkpat (Ppat_variant(label, arg))
|
||||||
|
| Tpat_record (subpatterns, _closed_flag) ->
|
||||||
|
let fields =
|
||||||
|
List.map
|
||||||
|
(fun (_, lbl, p) ->
|
||||||
let id = fresh lbl.lbl_name in
|
let id = fresh lbl.lbl_name in
|
||||||
Hashtbl.add labels id lbl;
|
Hashtbl.add labels id lbl;
|
||||||
Longident.Lident id)
|
(mknoloc (Longident.Lident id), loop p))
|
||||||
subpatterns
|
subpatterns
|
||||||
in
|
in
|
||||||
List.map
|
mkpat (Ppat_record (fields, Open))
|
||||||
(fun lst ->
|
|
||||||
let lst = List.map2 (fun lid pat ->
|
|
||||||
(mknoloc lid, pat)
|
|
||||||
) label_idents lst in
|
|
||||||
mkpat (Ppat_record (lst, Open)))
|
|
||||||
pats
|
|
||||||
| Tpat_array lst ->
|
| Tpat_array lst ->
|
||||||
let results = select (List.map loop lst) in
|
mkpat (Ppat_array (List.map loop lst))
|
||||||
List.map (fun lst -> mkpat (Ppat_array lst)) results
|
|
||||||
| Tpat_lazy p ->
|
| Tpat_lazy p ->
|
||||||
let results = loop p in
|
mkpat (Ppat_lazy (loop p))
|
||||||
List.map (fun p -> mkpat (Ppat_lazy p)) results
|
|
||||||
in
|
in
|
||||||
let ps = loop typed in
|
let ps = loop typed in
|
||||||
(ps, constrs, labels)
|
(ps, constrs, labels)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let ppat_of_type env ty =
|
||||||
|
match pats_of_type env ty with
|
||||||
|
[{pat_desc = Tpat_any}] ->
|
||||||
|
(Conv.mkpat Parsetree.Ppat_any, Hashtbl.create 0, Hashtbl.create 0)
|
||||||
|
| pats ->
|
||||||
|
Conv.conv (orify_many pats)
|
||||||
|
|
||||||
let do_check_partial ?pred exhaust loc casel pss = match pss with
|
let do_check_partial ?pred exhaust loc casel pss = match pss with
|
||||||
| [] ->
|
| [] ->
|
||||||
|
@ -1798,12 +1726,12 @@ let do_check_partial ?pred exhaust loc casel pss = match pss with
|
||||||
let v =
|
let v =
|
||||||
match pred with
|
match pred with
|
||||||
| Some pred ->
|
| Some pred ->
|
||||||
let (patterns,constrs,labels) = Conv.conv u in
|
let (pattern,constrs,labels) = Conv.conv u in
|
||||||
(* Hashtbl.iter (fun s (path, _) ->
|
(* Hashtbl.iter (fun s (path, _) ->
|
||||||
Printf.fprintf stderr "CONV: %s -> %s \n%!" s (Path.name path))
|
Printf.fprintf stderr "CONV: %s -> %s \n%!" s (Path.name path))
|
||||||
constrs
|
constrs
|
||||||
; *)
|
; *)
|
||||||
get_first (pred constrs labels) patterns
|
pred constrs labels pattern
|
||||||
| None -> Some u
|
| None -> Some u
|
||||||
in
|
in
|
||||||
begin match v with
|
begin match v with
|
||||||
|
@ -1839,8 +1767,10 @@ let do_check_partial ?pred exhaust loc casel pss = match pss with
|
||||||
fatal_error "Parmatch.check_partial"
|
fatal_error "Parmatch.check_partial"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
(*
|
||||||
let do_check_partial_normal loc casel pss =
|
let do_check_partial_normal loc casel pss =
|
||||||
do_check_partial exhaust loc casel pss
|
do_check_partial exhaust loc casel pss
|
||||||
|
*)
|
||||||
|
|
||||||
let do_check_partial_gadt pred loc casel pss =
|
let do_check_partial_gadt pred loc casel pss =
|
||||||
do_check_partial ~pred exhaust_gadt loc casel pss
|
do_check_partial ~pred exhaust_gadt loc casel pss
|
||||||
|
@ -1916,7 +1846,7 @@ let do_check_fragile_param exhaust loc casel pss =
|
||||||
| Rsome _ -> ())
|
| Rsome _ -> ())
|
||||||
exts
|
exts
|
||||||
|
|
||||||
let do_check_fragile_normal = do_check_fragile_param exhaust
|
(*let do_check_fragile_normal = do_check_fragile_param exhaust*)
|
||||||
let do_check_fragile_gadt = do_check_fragile_param exhaust_gadt
|
let do_check_fragile_gadt = do_check_fragile_param exhaust_gadt
|
||||||
|
|
||||||
(********************************)
|
(********************************)
|
||||||
|
@ -2012,19 +1942,11 @@ let check_partial_param do_check_partial do_check_fragile loc casel =
|
||||||
end else
|
end else
|
||||||
Partial
|
Partial
|
||||||
|
|
||||||
let check_partial =
|
(*let check_partial =
|
||||||
check_partial_param
|
check_partial_param
|
||||||
do_check_partial_normal
|
do_check_partial_normal
|
||||||
do_check_fragile_normal
|
do_check_fragile_normal*)
|
||||||
|
|
||||||
let check_partial_gadt pred loc casel =
|
let check_partial_gadt pred loc casel =
|
||||||
(*ignores GADT constructors *)
|
check_partial_param (do_check_partial_gadt pred)
|
||||||
let first_check = check_partial loc casel in
|
do_check_fragile_gadt loc casel
|
||||||
match first_check with
|
|
||||||
| Partial -> Partial
|
|
||||||
| Total ->
|
|
||||||
(* checks for missing GADT constructors *)
|
|
||||||
(* let casel =
|
|
||||||
match casel with [] -> [] | a :: l -> a :: l @ [a] in *)
|
|
||||||
check_partial_param (do_check_partial_gadt pred)
|
|
||||||
do_check_fragile_gadt loc casel
|
|
||||||
|
|
|
@ -51,6 +51,11 @@ val set_args_erase_mutable : pattern -> pattern list -> pattern list
|
||||||
val pat_of_constr : pattern -> constructor_description -> pattern
|
val pat_of_constr : pattern -> constructor_description -> pattern
|
||||||
val complete_constrs :
|
val complete_constrs :
|
||||||
pattern -> constructor_tag list -> constructor_description list
|
pattern -> constructor_tag list -> constructor_description list
|
||||||
|
val ppat_of_type :
|
||||||
|
Env.t -> type_expr ->
|
||||||
|
Parsetree.pattern *
|
||||||
|
(string, constructor_description) Hashtbl.t *
|
||||||
|
(string, label_description) Hashtbl.t
|
||||||
|
|
||||||
val pressure_variants: Env.t -> pattern list -> unit
|
val pressure_variants: Env.t -> pattern list -> unit
|
||||||
val check_partial_gadt:
|
val check_partial_gadt:
|
||||||
|
|
|
@ -827,7 +827,11 @@ let rec find_record_qual = function
|
||||||
| ({ txt = Longident.Ldot (modname, _) }, _) :: _ -> Some modname
|
| ({ txt = Longident.Ldot (modname, _) }, _) :: _ -> Some modname
|
||||||
| _ :: rest -> find_record_qual rest
|
| _ :: rest -> find_record_qual rest
|
||||||
|
|
||||||
let type_label_a_list ?labels loc closed env type_lbl_a opath lid_a_list =
|
let map_fold_cont f xs k =
|
||||||
|
List.fold_right (fun x k ys -> f x (fun y -> k (y :: ys)))
|
||||||
|
xs (fun ys -> k (List.rev ys)) []
|
||||||
|
|
||||||
|
let type_label_a_list ?labels loc closed env type_lbl_a opath lid_a_list k =
|
||||||
let lbl_a_list =
|
let lbl_a_list =
|
||||||
match lid_a_list, labels with
|
match lid_a_list, labels with
|
||||||
({txt=Longident.Lident s}, _)::_, Some labels when Hashtbl.mem labels s ->
|
({txt=Longident.Lident s}, _)::_, Some labels when Hashtbl.mem labels s ->
|
||||||
|
@ -857,7 +861,7 @@ let type_label_a_list ?labels loc closed env type_lbl_a opath lid_a_list =
|
||||||
(fun (_,lbl1,_) (_,lbl2,_) -> compare lbl1.lbl_pos lbl2.lbl_pos)
|
(fun (_,lbl1,_) (_,lbl2,_) -> compare lbl1.lbl_pos lbl2.lbl_pos)
|
||||||
lbl_a_list
|
lbl_a_list
|
||||||
in
|
in
|
||||||
List.map type_lbl_a lbl_a_list
|
map_fold_cont type_lbl_a lbl_a_list k
|
||||||
;;
|
;;
|
||||||
|
|
||||||
(* Checks over the labels mentioned in a record pattern:
|
(* Checks over the labels mentioned in a record pattern:
|
||||||
|
@ -917,32 +921,59 @@ type type_pat_mode =
|
||||||
| Normal
|
| Normal
|
||||||
| Inside_or
|
| Inside_or
|
||||||
|
|
||||||
|
(* Remember current state for backtracking.
|
||||||
|
No variable information, as we only backtrack on
|
||||||
|
patterns without variables (cf. assert statements). *)
|
||||||
|
type state =
|
||||||
|
{ snapshot: Btype.snapshot;
|
||||||
|
levels: Ctype.levels;
|
||||||
|
env: Env.t; }
|
||||||
|
let save_state env =
|
||||||
|
{ snapshot = Btype.snapshot ();
|
||||||
|
levels = Ctype.save_levels ();
|
||||||
|
env = !env; }
|
||||||
|
let set_state s env =
|
||||||
|
Btype.backtrack s.snapshot;
|
||||||
|
Ctype.set_levels s.levels;
|
||||||
|
env := s.env
|
||||||
|
|
||||||
(* type_pat propagates the expected type as well as maps for
|
(* type_pat propagates the expected type as well as maps for
|
||||||
constructors and labels.
|
constructors and labels.
|
||||||
Unification may update the typing environment. *)
|
Unification may update the typing environment. *)
|
||||||
let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
(* constrs <> None => called from parmatch: backtrack on or-patterns
|
||||||
let type_pat ?(mode=mode) ?(env=env) =
|
labels <> None => explode Ppat_any for gadts *)
|
||||||
|
let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty k =
|
||||||
|
let type_pat ?(constrs=constrs) ?(labels=labels) ?(mode=mode) ?(env=env) =
|
||||||
type_pat ~constrs ~labels ~no_existentials ~mode ~env in
|
type_pat ~constrs ~labels ~no_existentials ~mode ~env in
|
||||||
let loc = sp.ppat_loc in
|
let loc = sp.ppat_loc in
|
||||||
|
let rp k x : pattern = if constrs = None then k (rp x) else k x in
|
||||||
match sp.ppat_desc with
|
match sp.ppat_desc with
|
||||||
Ppat_any ->
|
Ppat_any ->
|
||||||
rp {
|
let k' d = rp k {
|
||||||
pat_desc = Tpat_any;
|
pat_desc = d;
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_type = expected_ty;
|
pat_type = expected_ty;
|
||||||
pat_attributes = sp.ppat_attributes;
|
pat_attributes = sp.ppat_attributes;
|
||||||
pat_env = !env }
|
pat_env = !env }
|
||||||
|
in
|
||||||
|
if labels <> None then
|
||||||
|
let (sp, constrs, labels) = Parmatch.ppat_of_type !env expected_ty in
|
||||||
|
if sp.ppat_desc = Parsetree.Ppat_any then k' Tpat_any
|
||||||
|
else type_pat ~constrs:(Some constrs) ~labels:None sp expected_ty k
|
||||||
|
else k' Tpat_any
|
||||||
| Ppat_var name ->
|
| Ppat_var name ->
|
||||||
|
assert (constrs = None);
|
||||||
let id = enter_variable loc name expected_ty in
|
let id = enter_variable loc name expected_ty in
|
||||||
rp {
|
rp k {
|
||||||
pat_desc = Tpat_var (id, name);
|
pat_desc = Tpat_var (id, name);
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_type = expected_ty;
|
pat_type = expected_ty;
|
||||||
pat_attributes = sp.ppat_attributes;
|
pat_attributes = sp.ppat_attributes;
|
||||||
pat_env = !env }
|
pat_env = !env }
|
||||||
| Ppat_unpack name ->
|
| Ppat_unpack name ->
|
||||||
|
assert (constrs = None);
|
||||||
let id = enter_variable loc name expected_ty ~is_module:true in
|
let id = enter_variable loc name expected_ty ~is_module:true in
|
||||||
rp {
|
rp k {
|
||||||
pat_desc = Tpat_var (id, name);
|
pat_desc = Tpat_var (id, name);
|
||||||
pat_loc = sp.ppat_loc;
|
pat_loc = sp.ppat_loc;
|
||||||
pat_extra=[Tpat_unpack, loc, sp.ppat_attributes];
|
pat_extra=[Tpat_unpack, loc, sp.ppat_attributes];
|
||||||
|
@ -952,6 +983,7 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
| Ppat_constraint({ppat_desc=Ppat_var name; ppat_loc=lloc},
|
| Ppat_constraint({ppat_desc=Ppat_var name; ppat_loc=lloc},
|
||||||
({ptyp_desc=Ptyp_poly _} as sty)) ->
|
({ptyp_desc=Ptyp_poly _} as sty)) ->
|
||||||
(* explicitly polymorphic type *)
|
(* explicitly polymorphic type *)
|
||||||
|
assert (constrs = None);
|
||||||
let cty, force = Typetexp.transl_simple_type_delayed !env sty in
|
let cty, force = Typetexp.transl_simple_type_delayed !env sty in
|
||||||
let ty = cty.ctyp_type in
|
let ty = cty.ctyp_type in
|
||||||
unify_pat_types lloc !env ty expected_ty;
|
unify_pat_types lloc !env ty expected_ty;
|
||||||
|
@ -963,7 +995,7 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
end_def ();
|
end_def ();
|
||||||
generalize ty';
|
generalize ty';
|
||||||
let id = enter_variable lloc name ty' in
|
let id = enter_variable lloc name ty' in
|
||||||
rp {
|
rp k {
|
||||||
pat_desc = Tpat_var (id, name);
|
pat_desc = Tpat_var (id, name);
|
||||||
pat_loc = lloc;
|
pat_loc = lloc;
|
||||||
pat_extra = [Tpat_constraint cty, loc, sp.ppat_attributes];
|
pat_extra = [Tpat_constraint cty, loc, sp.ppat_attributes];
|
||||||
|
@ -974,21 +1006,22 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
| _ -> assert false
|
| _ -> assert false
|
||||||
end
|
end
|
||||||
| Ppat_alias(sq, name) ->
|
| Ppat_alias(sq, name) ->
|
||||||
let q = type_pat sq expected_ty in
|
assert (constrs = None);
|
||||||
begin_def ();
|
type_pat sq expected_ty (fun q ->
|
||||||
let ty_var = build_as_type !env q in
|
begin_def ();
|
||||||
end_def ();
|
let ty_var = build_as_type !env q in
|
||||||
generalize ty_var;
|
end_def ();
|
||||||
let id = enter_variable ~is_as_variable:true loc name ty_var in
|
generalize ty_var;
|
||||||
rp {
|
let id = enter_variable ~is_as_variable:true loc name ty_var in
|
||||||
pat_desc = Tpat_alias(q, id, name);
|
rp k {
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_desc = Tpat_alias(q, id, name);
|
||||||
pat_type = q.pat_type;
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_attributes = sp.ppat_attributes;
|
pat_type = q.pat_type;
|
||||||
pat_env = !env }
|
pat_attributes = sp.ppat_attributes;
|
||||||
|
pat_env = !env })
|
||||||
| Ppat_constant cst ->
|
| Ppat_constant cst ->
|
||||||
unify_pat_types loc !env (type_constant cst) expected_ty;
|
unify_pat_types loc !env (type_constant cst) expected_ty;
|
||||||
rp {
|
rp k {
|
||||||
pat_desc = Tpat_constant cst;
|
pat_desc = Tpat_constant cst;
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_type = expected_ty;
|
pat_type = expected_ty;
|
||||||
|
@ -1006,7 +1039,7 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
in
|
in
|
||||||
let p = if c1 <= c2 then loop c1 c2 else loop c2 c1 in
|
let p = if c1 <= c2 then loop c1 c2 else loop c2 c1 in
|
||||||
let p = {p with ppat_loc=loc} in
|
let p = {p with ppat_loc=loc} in
|
||||||
type_pat p expected_ty
|
type_pat ~labels:None p expected_ty k
|
||||||
(* TODO: record 'extra' to remember about interval *)
|
(* TODO: record 'extra' to remember about interval *)
|
||||||
| Ppat_interval _ ->
|
| Ppat_interval _ ->
|
||||||
raise (Error (loc, !env, Invalid_interval))
|
raise (Error (loc, !env, Invalid_interval))
|
||||||
|
@ -1016,13 +1049,13 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
let spl_ann = List.map (fun p -> (p,newvar ())) spl in
|
let spl_ann = List.map (fun p -> (p,newvar ())) spl in
|
||||||
let ty = newty (Ttuple(List.map snd spl_ann)) in
|
let ty = newty (Ttuple(List.map snd spl_ann)) in
|
||||||
unify_pat_types loc !env ty expected_ty;
|
unify_pat_types loc !env ty expected_ty;
|
||||||
let pl = List.map (fun (p,t) -> type_pat p t) spl_ann in
|
map_fold_cont (fun (p,t) -> type_pat p t) spl_ann (fun pl ->
|
||||||
rp {
|
rp k {
|
||||||
pat_desc = Tpat_tuple pl;
|
pat_desc = Tpat_tuple pl;
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_type = expected_ty;
|
pat_type = expected_ty;
|
||||||
pat_attributes = sp.ppat_attributes;
|
pat_attributes = sp.ppat_attributes;
|
||||||
pat_env = !env }
|
pat_env = !env })
|
||||||
| Ppat_construct(lid, sarg) ->
|
| Ppat_construct(lid, sarg) ->
|
||||||
let opath =
|
let opath =
|
||||||
try
|
try
|
||||||
|
@ -1090,13 +1123,14 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
in
|
in
|
||||||
if constr.cstr_inlined <> None then List.iter check_non_escaping sargs;
|
if constr.cstr_inlined <> None then List.iter check_non_escaping sargs;
|
||||||
|
|
||||||
let args = List.map2 (fun p t -> type_pat p t) sargs ty_args in
|
map_fold_cont (fun (p,t) -> type_pat p t) (List.combine sargs ty_args)
|
||||||
rp {
|
(fun args ->
|
||||||
pat_desc=Tpat_construct(lid, constr, args);
|
rp k {
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_desc=Tpat_construct(lid, constr, args);
|
||||||
pat_type = expected_ty;
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_attributes = sp.ppat_attributes;
|
pat_type = expected_ty;
|
||||||
pat_env = !env }
|
pat_attributes = sp.ppat_attributes;
|
||||||
|
pat_env = !env })
|
||||||
| Ppat_variant(l, sarg) ->
|
| Ppat_variant(l, sarg) ->
|
||||||
let arg_type = match sarg with None -> [] | Some _ -> [newvar()] in
|
let arg_type = match sarg with None -> [] | Some _ -> [newvar()] in
|
||||||
let row = { row_fields =
|
let row = { row_fields =
|
||||||
|
@ -1107,18 +1141,19 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
row_fixed = false;
|
row_fixed = false;
|
||||||
row_name = None } in
|
row_name = None } in
|
||||||
unify_pat_types loc !env (newty (Tvariant row)) expected_ty;
|
unify_pat_types loc !env (newty (Tvariant row)) expected_ty;
|
||||||
let arg =
|
let k arg =
|
||||||
(* PR#6235: propagate type information *)
|
rp k {
|
||||||
match sarg, arg_type with
|
|
||||||
Some p, [ty] -> Some (type_pat p ty)
|
|
||||||
| _ -> None
|
|
||||||
in
|
|
||||||
rp {
|
|
||||||
pat_desc = Tpat_variant(l, arg, ref {row with row_more = newvar()});
|
pat_desc = Tpat_variant(l, arg, ref {row with row_more = newvar()});
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_type = expected_ty;
|
pat_type = expected_ty;
|
||||||
pat_attributes = sp.ppat_attributes;
|
pat_attributes = sp.ppat_attributes;
|
||||||
pat_env = !env }
|
pat_env = !env }
|
||||||
|
in begin
|
||||||
|
(* PR#6235: propagate type information *)
|
||||||
|
match sarg, arg_type with
|
||||||
|
Some p, [ty] -> type_pat p ty (fun p -> k (Some p))
|
||||||
|
| _ -> k None
|
||||||
|
end
|
||||||
| Ppat_record(lid_sp_list, closed) ->
|
| Ppat_record(lid_sp_list, closed) ->
|
||||||
if lid_sp_list = [] then
|
if lid_sp_list = [] then
|
||||||
Syntaxerr.ill_formed_ast loc "Records cannot be empty.";
|
Syntaxerr.ill_formed_ast loc "Records cannot be empty.";
|
||||||
|
@ -1128,7 +1163,7 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
Some (p0, p, true), expected_ty
|
Some (p0, p, true), expected_ty
|
||||||
with Not_found -> None, newvar ()
|
with Not_found -> None, newvar ()
|
||||||
in
|
in
|
||||||
let type_label_pat (label_lid, label, sarg) =
|
let type_label_pat (label_lid, label, sarg) k =
|
||||||
begin_def ();
|
begin_def ();
|
||||||
let (vars, ty_arg, ty_res) = instance_label false label in
|
let (vars, ty_arg, ty_res) = instance_label false label in
|
||||||
if vars = [] then end_def ();
|
if vars = [] then end_def ();
|
||||||
|
@ -1138,55 +1173,72 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
raise(Error(label_lid.loc, !env,
|
raise(Error(label_lid.loc, !env,
|
||||||
Label_mismatch(label_lid.txt, trace)))
|
Label_mismatch(label_lid.txt, trace)))
|
||||||
end;
|
end;
|
||||||
let arg = type_pat sarg ty_arg in
|
type_pat sarg ty_arg (fun arg ->
|
||||||
if vars <> [] then begin
|
if vars <> [] then begin
|
||||||
end_def ();
|
end_def ();
|
||||||
generalize ty_arg;
|
generalize ty_arg;
|
||||||
List.iter generalize vars;
|
List.iter generalize vars;
|
||||||
let instantiated tv =
|
let instantiated tv =
|
||||||
let tv = expand_head !env tv in
|
let tv = expand_head !env tv in
|
||||||
not (is_Tvar tv) || tv.level <> generic_level in
|
not (is_Tvar tv) || tv.level <> generic_level in
|
||||||
if List.exists instantiated vars then
|
if List.exists instantiated vars then
|
||||||
raise (Error(label_lid.loc, !env, Polymorphic_label label_lid.txt))
|
raise
|
||||||
end;
|
(Error(label_lid.loc, !env, Polymorphic_label label_lid.txt))
|
||||||
(label_lid, label, arg)
|
end;
|
||||||
|
k (label_lid, label, arg))
|
||||||
in
|
in
|
||||||
let lbl_pat_list =
|
let k' k lbl_pat_list =
|
||||||
wrap_disambiguate "This record pattern is expected to have" expected_ty
|
check_recordpat_labels loc lbl_pat_list closed;
|
||||||
(type_label_a_list ?labels loc false !env type_label_pat opath)
|
unify_pat_types loc !env record_ty expected_ty;
|
||||||
lid_sp_list
|
rp k {
|
||||||
in
|
|
||||||
check_recordpat_labels loc lbl_pat_list closed;
|
|
||||||
unify_pat_types loc !env record_ty expected_ty;
|
|
||||||
rp {
|
|
||||||
pat_desc = Tpat_record (lbl_pat_list, closed);
|
pat_desc = Tpat_record (lbl_pat_list, closed);
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_type = expected_ty;
|
pat_type = expected_ty;
|
||||||
pat_attributes = sp.ppat_attributes;
|
pat_attributes = sp.ppat_attributes;
|
||||||
pat_env = !env }
|
pat_env = !env }
|
||||||
|
in
|
||||||
|
if constrs = None then
|
||||||
|
k (wrap_disambiguate "This record pattern is expected to have"
|
||||||
|
expected_ty
|
||||||
|
(type_label_a_list ?labels loc false !env type_label_pat opath
|
||||||
|
lid_sp_list)
|
||||||
|
(k' (fun x -> x)))
|
||||||
|
else
|
||||||
|
type_label_a_list ?labels loc false !env type_label_pat opath
|
||||||
|
lid_sp_list (k' k)
|
||||||
| Ppat_array spl ->
|
| Ppat_array spl ->
|
||||||
let ty_elt = newvar() in
|
let ty_elt = newvar() in
|
||||||
unify_pat_types
|
unify_pat_types
|
||||||
loc !env (instance_def (Predef.type_array ty_elt)) expected_ty;
|
loc !env (instance_def (Predef.type_array ty_elt)) expected_ty;
|
||||||
let spl_ann = List.map (fun p -> (p,newvar())) spl in
|
let spl_ann = List.map (fun p -> (p,newvar())) spl in
|
||||||
let pl = List.map (fun (p,t) -> type_pat p ty_elt) spl_ann in
|
map_fold_cont (fun (p,t) -> type_pat p ty_elt) spl_ann (fun pl ->
|
||||||
rp {
|
rp k {
|
||||||
pat_desc = Tpat_array pl;
|
pat_desc = Tpat_array pl;
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_type = expected_ty;
|
pat_type = expected_ty;
|
||||||
pat_attributes = sp.ppat_attributes;
|
pat_attributes = sp.ppat_attributes;
|
||||||
pat_env = !env }
|
pat_env = !env })
|
||||||
| Ppat_or(sp1, sp2) ->
|
| Ppat_or(sp1, sp2) ->
|
||||||
|
if constrs <> None &&
|
||||||
|
match sp1.ppat_desc, sp2.ppat_desc with
|
||||||
|
Ppat_constant _, _ | _, Ppat_constant _ -> false
|
||||||
|
| _ -> true
|
||||||
|
then
|
||||||
|
let state = save_state env in
|
||||||
|
try type_pat sp1 expected_ty k with exn when exn <> Exit ->
|
||||||
|
set_state state env;
|
||||||
|
type_pat sp2 expected_ty k
|
||||||
|
else
|
||||||
let initial_pattern_variables = !pattern_variables in
|
let initial_pattern_variables = !pattern_variables in
|
||||||
let p1 = type_pat ~mode:Inside_or sp1 expected_ty in
|
let p1 = type_pat ~mode:Inside_or sp1 expected_ty (fun x -> x) in
|
||||||
let p1_variables = !pattern_variables in
|
let p1_variables = !pattern_variables in
|
||||||
pattern_variables := initial_pattern_variables;
|
pattern_variables := initial_pattern_variables;
|
||||||
let p2 = type_pat ~mode:Inside_or sp2 expected_ty in
|
let p2 = type_pat ~mode:Inside_or sp2 expected_ty (fun x -> x) in
|
||||||
let p2_variables = !pattern_variables in
|
let p2_variables = !pattern_variables in
|
||||||
let alpha_env =
|
let alpha_env =
|
||||||
enter_orpat_variables loc !env p1_variables p2_variables in
|
enter_orpat_variables loc !env p1_variables p2_variables in
|
||||||
pattern_variables := p1_variables;
|
pattern_variables := p1_variables;
|
||||||
rp {
|
rp k {
|
||||||
pat_desc = Tpat_or(p1, alpha_pat alpha_env p2, None);
|
pat_desc = Tpat_or(p1, alpha_pat alpha_env p2, None);
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_type = expected_ty;
|
pat_type = expected_ty;
|
||||||
|
@ -1196,13 +1248,13 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
let nv = newvar () in
|
let nv = newvar () in
|
||||||
unify_pat_types loc !env (instance_def (Predef.type_lazy_t nv))
|
unify_pat_types loc !env (instance_def (Predef.type_lazy_t nv))
|
||||||
expected_ty;
|
expected_ty;
|
||||||
let p1 = type_pat sp1 nv in
|
type_pat sp1 nv (fun p1 ->
|
||||||
rp {
|
rp k {
|
||||||
pat_desc = Tpat_lazy p1;
|
pat_desc = Tpat_lazy p1;
|
||||||
pat_loc = loc; pat_extra=[];
|
pat_loc = loc; pat_extra=[];
|
||||||
pat_type = expected_ty;
|
pat_type = expected_ty;
|
||||||
pat_attributes = sp.ppat_attributes;
|
pat_attributes = sp.ppat_attributes;
|
||||||
pat_env = !env }
|
pat_env = !env })
|
||||||
| Ppat_constraint(sp, sty) ->
|
| Ppat_constraint(sp, sty) ->
|
||||||
(* Separate when not already separated by !principal *)
|
(* Separate when not already separated by !principal *)
|
||||||
let separate = true in
|
let separate = true in
|
||||||
|
@ -1217,27 +1269,28 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
|
||||||
end else ty, ty
|
end else ty, ty
|
||||||
in
|
in
|
||||||
unify_pat_types loc !env ty expected_ty;
|
unify_pat_types loc !env ty expected_ty;
|
||||||
let p = type_pat sp expected_ty' in
|
type_pat sp expected_ty' (fun p ->
|
||||||
(*Format.printf "%a@.%a@."
|
(*Format.printf "%a@.%a@."
|
||||||
Printtyp.raw_type_expr ty
|
Printtyp.raw_type_expr ty
|
||||||
Printtyp.raw_type_expr p.pat_type;*)
|
Printtyp.raw_type_expr p.pat_type;*)
|
||||||
pattern_force := force :: !pattern_force;
|
pattern_force := force :: !pattern_force;
|
||||||
let extra = (Tpat_constraint cty, loc, sp.ppat_attributes) in
|
let extra = (Tpat_constraint cty, loc, sp.ppat_attributes) in
|
||||||
if separate then
|
let p =
|
||||||
match p.pat_desc with
|
if not separate then p else
|
||||||
Tpat_var (id,s) ->
|
match p.pat_desc with
|
||||||
{p with pat_type = ty;
|
Tpat_var (id,s) ->
|
||||||
pat_desc = Tpat_alias
|
{p with pat_type = ty;
|
||||||
({p with pat_desc = Tpat_any; pat_attributes = []}, id,s);
|
pat_desc = Tpat_alias
|
||||||
pat_extra = [extra];
|
({p with pat_desc = Tpat_any; pat_attributes = []}, id,s);
|
||||||
}
|
pat_extra = [extra];
|
||||||
| _ -> {p with pat_type = ty;
|
}
|
||||||
pat_extra = extra :: p.pat_extra}
|
| _ -> {p with pat_type = ty;
|
||||||
else p
|
pat_extra = extra :: p.pat_extra}
|
||||||
|
in k p)
|
||||||
| Ppat_type lid ->
|
| Ppat_type lid ->
|
||||||
let (path, p,ty) = build_or_pat !env loc lid.txt in
|
let (path, p,ty) = build_or_pat !env loc lid.txt in
|
||||||
unify_pat_types loc !env ty expected_ty;
|
unify_pat_types loc !env ty expected_ty;
|
||||||
{ p with pat_extra =
|
k { p with pat_extra =
|
||||||
(Tpat_type (path, lid), loc, sp.ppat_attributes) :: p.pat_extra }
|
(Tpat_type (path, lid), loc, sp.ppat_attributes) :: p.pat_extra }
|
||||||
| Ppat_exception _ ->
|
| Ppat_exception _ ->
|
||||||
raise (Error (loc, !env, Exception_pattern_below_toplevel))
|
raise (Error (loc, !env, Exception_pattern_below_toplevel))
|
||||||
|
@ -1250,7 +1303,7 @@ let type_pat ?(allow_existentials=false) ?constrs ?labels
|
||||||
try
|
try
|
||||||
let r =
|
let r =
|
||||||
type_pat ~no_existentials:(not allow_existentials) ~constrs ~labels
|
type_pat ~no_existentials:(not allow_existentials) ~constrs ~labels
|
||||||
~mode:Normal ~env sp expected_ty in
|
~mode:Normal ~env sp expected_ty (fun x -> x) in
|
||||||
iter_pattern (fun p -> p.pat_env <- !env) r;
|
iter_pattern (fun p -> p.pat_env <- !env) r;
|
||||||
newtype_level := None;
|
newtype_level := None;
|
||||||
r
|
r
|
||||||
|
@ -2089,9 +2142,9 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
|
||||||
let lbl_exp_list =
|
let lbl_exp_list =
|
||||||
wrap_disambiguate "This record expression is expected to have" ty_record
|
wrap_disambiguate "This record expression is expected to have" ty_record
|
||||||
(type_label_a_list loc closed env
|
(type_label_a_list loc closed env
|
||||||
(type_label_exp true env loc ty_record)
|
(fun e k -> k (type_label_exp true env loc ty_record e))
|
||||||
opath)
|
opath lid_sexp_list)
|
||||||
lid_sexp_list
|
(fun x -> x)
|
||||||
in
|
in
|
||||||
unify_exp_types loc env ty_record (instance env ty_expected);
|
unify_exp_types loc env ty_record (instance env ty_expected);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue