Skip to content

Commit cad125d

Browse files
authored
Fix modes from or-patterns (#50)
1 parent 4efdb72 commit cad125d

File tree

8 files changed

+93
-29
lines changed

8 files changed

+93
-29
lines changed

lambda/matching.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,8 +1482,8 @@ and precompile_or ~arg_id (cls : Simple.clause list) ors args def k =
14821482
(* bound variables of the or-pattern and used in the orpm
14831483
actions *)
14841484
Typedtree.pat_bound_idents_full orp
1485-
|> List.filter (fun (id, _, _, _) -> Ident.Set.mem id pm_fv)
1486-
|> List.map (fun (id, _, ty, _) ->
1485+
|> List.filter (fun (id, _) -> Ident.Set.mem id pm_fv)
1486+
|> List.map (fun (id, ty) ->
14871487
(id, Typeopt.value_kind orp.pat_env ty))
14881488
in
14891489
let or_num = next_raise_count () in
@@ -3569,10 +3569,10 @@ let for_let ~scopes loc param pat body =
35693569
let catch_ids = pat_bound_idents_full pat in
35703570
let ids_with_kinds =
35713571
List.map
3572-
(fun (id, _, typ, _) -> (id, Typeopt.value_kind pat.pat_env typ))
3572+
(fun (id, typ) -> (id, Typeopt.value_kind pat.pat_env typ))
35733573
catch_ids
35743574
in
3575-
let ids = List.map (fun (id, _, _, _) -> id) catch_ids in
3575+
let ids = List.map (fun (id, _) -> id) catch_ids in
35763576
let bind =
35773577
map_return (assign_pat ~scopes opt nraise ids loc pat) param in
35783578
if !opt then

lambda/translcore.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,9 +1214,9 @@ and transl_match ~scopes e arg pat_expr_list partial =
12141214
(* Simplif doesn't like it if binders are not uniq, so we make sure to
12151215
use different names in the value and the exception branches. *)
12161216
let ids_full = Typedtree.pat_bound_idents_full pv in
1217-
let ids = List.map (fun (id, _, _, _) -> id) ids_full in
1217+
let ids = List.map (fun (id, _) -> id) ids_full in
12181218
let ids_kinds =
1219-
List.map (fun (id, _, ty, _) -> id, Typeopt.value_kind pv.pat_env ty)
1219+
List.map (fun (id, ty) -> id, Typeopt.value_kind pv.pat_env ty)
12201220
ids_full
12211221
in
12221222
let vids = List.map Ident.rename ids in

testsuite/tests/typing-local/local.ml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,3 +1718,38 @@ let promote (local_ x) = +x
17181718
[%%expect{|
17191719
val promote : local_ int -> int = <fun>
17201720
|}]
1721+
1722+
(* Or-patterns *)
1723+
let foo (local_ x) y =
1724+
match y, x with
1725+
| Some z, None | None, Some z -> z
1726+
| None, None | Some _, Some _ -> assert false
1727+
[%%expect{|
1728+
val foo : local_ 'a option -> 'a option -> local_ 'a = <fun>
1729+
|}]
1730+
1731+
let foo (local_ x) y =
1732+
match x, y with
1733+
| Some z, None | None, Some z -> z
1734+
| None, None | Some _, Some _ -> assert false
1735+
[%%expect{|
1736+
val foo : local_ 'a option -> 'a option -> local_ 'a = <fun>
1737+
|}]
1738+
1739+
let (Some z, _, _) | (None, Some z, _)
1740+
| (None, None, z) = (Some (ref 0), (local_ (Some (ref 0))), (ref 0))
1741+
[%%expect{|
1742+
Line 1, characters 33-34:
1743+
1 | let (Some z, _, _) | (None, Some z, _)
1744+
^
1745+
Error: This value escapes its region
1746+
|}]
1747+
1748+
let (Some z, _, _) | (None, Some z, _)
1749+
| (None, None, z) = ((local_ Some (ref 0)), (Some (ref 0)), (ref 0))
1750+
[%%expect{|
1751+
Line 1, characters 10-11:
1752+
1 | let (Some z, _, _) | (None, Some z, _)
1753+
^
1754+
Error: This value escapes its region
1755+
|}]

typing/typeclass.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,8 +1204,10 @@ and class_expr_aux cl_num val_env met_env scl =
12041204
Typecore.type_let In_class_def val_env rec_flag sdefs in
12051205
let (vals, met_env) =
12061206
List.fold_right
1207-
(fun (id, id_loc, _typ, mode) (vals, met_env) ->
1208-
Typecore.escape ~loc:id_loc.loc ~env:val_env mode;
1207+
(fun (id, modes) (vals, met_env) ->
1208+
List.iter
1209+
(fun (loc, mode) -> Typecore.escape ~loc ~env:val_env mode)
1210+
modes;
12091211
let path = Pident id in
12101212
(* do not mark the value as used *)
12111213
let vd = Env.find_value path val_env in
@@ -1235,7 +1237,7 @@ and class_expr_aux cl_num val_env met_env scl =
12351237
((id', expr)
12361238
:: vals,
12371239
Env.add_value id' desc met_env))
1238-
(let_bound_idents_full defs)
1240+
(let_bound_idents_with_modes defs)
12391241
([], met_env)
12401242
in
12411243
let cl = class_expr cl_num val_env met_env scl' in

typing/typecore.ml

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -595,10 +595,12 @@ let enter_orpat_variables loc env p1_vs p2_vs =
595595
let rec unify_vars p1_vs p2_vs =
596596
let vars vs = List.map (fun {pv_id; _} -> pv_id) vs in
597597
match p1_vs, p2_vs with
598-
| {pv_id = x1; pv_type = t1; _}::rem1, {pv_id = x2; pv_type = t2; _}::rem2
598+
| ({pv_id = x1; pv_type = t1; pv_mode = m1; _} as pv1)::rem1,
599+
{pv_id = x2; pv_type = t2; pv_mode = m2; _}::rem2
599600
when Ident.equal x1 x2 ->
600601
if x1==x2 then
601-
unify_vars rem1 rem2
602+
let vars, alist = unify_vars rem1 rem2 in
603+
pv1 :: vars, alist
602604
else begin
603605
begin try
604606
unify_var env (newvar ()) t1;
@@ -607,9 +609,12 @@ let enter_orpat_variables loc env p1_vs p2_vs =
607609
| Unify trace ->
608610
raise(Error(loc, env, Or_pattern_type_clash(x1, trace)))
609611
end;
610-
(x2,x1)::unify_vars rem1 rem2
612+
let m = Value_mode.join [m1; m2] in
613+
let var = { pv1 with pv_mode = m } in
614+
let vars, alist = unify_vars rem1 rem2 in
615+
var :: vars, (x2, x1) :: alist
611616
end
612-
| [],[] -> []
617+
| [],[] -> [], []
613618
| {pv_id; _}::_, [] | [],{pv_id; _}::_ ->
614619
raise (Error (loc, env, Orpat_vars (pv_id, [])))
615620
| {pv_id = x; _}::_, {pv_id = y; _}::_ ->
@@ -2027,10 +2032,11 @@ and type_pat_aux
20272032
| Error _, Ok p ->
20282033
rp k p
20292034
| Ok p1, Ok p2 ->
2030-
let alpha_env =
2031-
enter_orpat_variables loc !env p1_variables p2_variables in
2035+
let vars, alpha_env =
2036+
enter_orpat_variables loc !env p1_variables p2_variables
2037+
in
20322038
let p2 = alpha_pat alpha_env p2 in
2033-
pattern_variables := p1_variables;
2039+
pattern_variables := vars;
20342040
module_variables := p1_module_variables;
20352041
let make_pat desc =
20362042
{ pat_desc = desc;

typing/typedtree.ml

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -761,11 +761,11 @@ let rec iter_bound_idents
761761
: type k . _ -> k general_pattern -> _
762762
= fun f pat ->
763763
match pat.pat_desc with
764-
| Tpat_var (id,s) ->
765-
f (id,s,pat.pat_type,pat.pat_mode)
766-
| Tpat_alias(p, id, s) ->
764+
| Tpat_var (id, _) ->
765+
f (id, pat.pat_type)
766+
| Tpat_alias(p, id, _) ->
767767
iter_bound_idents f p;
768-
f (id,s,pat.pat_type,pat.pat_mode)
768+
f (id, pat.pat_type)
769769
| Tpat_or(p1, _, _) ->
770770
(* Invariant : both arguments bind the same variables *)
771771
iter_bound_idents f p1
@@ -781,7 +781,7 @@ let rev_pat_bound_idents_full pat =
781781
!idents_full
782782
783783
let rev_only_idents idents_full =
784-
List.rev_map (fun (id,_,_,_) -> id) idents_full
784+
List.rev_map (fun (id,_) -> id) idents_full
785785
786786
let pat_bound_idents_full pat =
787787
List.rev (rev_pat_bound_idents_full pat)
@@ -794,6 +794,23 @@ let rev_let_bound_idents_full bindings =
794794
List.iter (fun vb -> iter_bound_idents add vb.vb_pat) bindings;
795795
!idents_full
796796
797+
let let_bound_idents_with_modes bindings =
798+
let modes = Ident.Tbl.create 3 in
799+
let rec loop : type k . k general_pattern -> _ =
800+
fun pat ->
801+
match pat.pat_desc with
802+
| Tpat_var (id, { loc }) ->
803+
Ident.Tbl.add modes id (loc, pat.pat_mode)
804+
| Tpat_alias(p, id, { loc }) ->
805+
loop p;
806+
Ident.Tbl.add modes id (loc, pat.pat_mode)
807+
| d -> shallow_iter_pattern_desc { f = loop } d
808+
in
809+
List.iter (fun vb -> loop vb.vb_pat) bindings;
810+
List.rev_map
811+
(fun (id, _) -> id, List.rev (Ident.Tbl.find_all modes id))
812+
(rev_let_bound_idents_full bindings)
813+
797814
let let_bound_idents_full bindings =
798815
List.rev (rev_let_bound_idents_full bindings)
799816
let let_bound_idents pat =

typing/typedtree.mli

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -803,8 +803,10 @@ val exists_pattern: (pattern -> bool) -> pattern -> bool
803803

804804
val let_bound_idents: value_binding list -> Ident.t list
805805
val let_bound_idents_full:
806-
value_binding list
807-
-> (Ident.t * string loc * Types.type_expr * Types.Value_mode.t) list
806+
value_binding list -> (Ident.t * Types.type_expr) list
807+
val let_bound_idents_with_modes:
808+
value_binding list
809+
-> (Ident.t * (Location.t * Types.Value_mode.t) list) list
808810

809811
(** Alpha conversion of patterns *)
810812
val alpha_pat:
@@ -815,8 +817,7 @@ val mkloc: 'a -> Location.t -> 'a Asttypes.loc
815817

816818
val pat_bound_idents: 'k general_pattern -> Ident.t list
817819
val pat_bound_idents_full:
818-
'k general_pattern
819-
-> (Ident.t * string loc * Types.type_expr * Types.Value_mode.t) list
820+
'k general_pattern -> (Ident.t * Types.type_expr) list
820821

821822
(** Splits an or pattern into its value (left) and exception (right) parts. *)
822823
val split_pattern:

typing/typemod.ml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2170,11 +2170,14 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr =
21702170
(* Note: Env.find_value does not trigger the value_used event. Values
21712171
will be marked as being used during the signature inclusion test. *)
21722172
Tstr_value(rec_flag, defs),
2173-
List.map (fun (id, { Asttypes.loc; _ }, _typ, mode)->
2174-
Typecore.escape ~loc ~env:newenv mode;
2175-
Signature_names.check_value names loc id;
2173+
List.map (fun (id, modes) ->
2174+
List.iter
2175+
(fun (loc, mode) -> Typecore.escape ~loc ~env:newenv mode)
2176+
modes;
2177+
let (first_loc, _) = List.hd modes in
2178+
Signature_names.check_value names first_loc id;
21762179
Sig_value(id, Env.find_value (Pident id) newenv, Exported)
2177-
) (let_bound_idents_full defs),
2180+
) (let_bound_idents_with_modes defs),
21782181
newenv
21792182
| Pstr_primitive sdesc ->
21802183
let (desc, newenv) = Typedecl.transl_value_decl env loc sdesc in

0 commit comments

Comments
 (0)