Skip to content

Commit 56703cd

Browse files
committed
Typecheck x|>f and f @@ x as (f x) (cherry picked from commit 8b8168e)
1 parent eb66785 commit 56703cd

File tree

4 files changed

+61
-28
lines changed

4 files changed

+61
-28
lines changed

testsuite/tests/prim-revapply/apply.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
(* TEST
2+
flags="-w +48"
23
*)
34

45
external ( @@ ) : ('a -> 'b) -> 'a -> 'b = "%apply"
@@ -37,3 +38,7 @@ let _ =
3738
h @@ g @@ f @@ 3; (* 37 *)
3839
add 4 @@ g @@ f @@ add 3 @@ add 2 @@ 3; (* 260 *)
3940
]
41+
42+
(* PR#10081 *)
43+
let bump ?(cap = 100) x = min cap (x + 1)
44+
let _f x = bump @@ x (* no warning 48 *)

testsuite/tests/prim-revapply/revapply.ml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
(* TEST
2+
flags="-w +48"
23
*)
34

45
external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply"
@@ -19,3 +20,13 @@ let _ =
1920
3 |> f |> g |> h; (* 37 *)
2021
3 |> add 2 |> add 3 |> f |> g |> add 4; (* 260 *)
2122
]
23+
24+
25+
(* PR#10081 *)
26+
let bump ?(cap = 100) x = min cap (x + 1)
27+
let _f x = x |> bump (* no warning 48 *)
28+
29+
(* PR#10081 *)
30+
type t = A | B
31+
type s = A | B
32+
let _f (x : t) = x |> function A -> 0 | B -> 1

testsuite/tests/typing-misc/printing.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,6 @@ and bar () =
113113
Line 4, characters 7-29:
114114
4 | x |> List.fold_left max 0 x
115115
^^^^^^^^^^^^^^^^^^^^^^
116-
Error: This expression has type int but an expression was expected of type
117-
int list -> 'a
116+
Error: This expression has type int
117+
This is not a function; it cannot be applied.
118118
|}]

typing/typecore.ml

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2638,6 +2638,17 @@ let unify_exp env exp expected_ty =
26382638
with Error(loc, env, Expr_type_clash(trace, tfc, None)) ->
26392639
raise (Error(loc, env, Expr_type_clash(trace, tfc, Some exp.exp_desc)))
26402640

2641+
(* If [is_inferred e] is true, [e] will be typechecked without using
2642+
the "expected type" provided by the context. *)
2643+
2644+
let rec is_inferred sexp =
2645+
match sexp.pexp_desc with
2646+
| Pexp_ident _ | Pexp_apply _ | Pexp_field _ | Pexp_constraint _
2647+
| Pexp_coerce _ | Pexp_send _ | Pexp_new _ -> true
2648+
| Pexp_sequence (_, e) | Pexp_open (_, e) -> is_inferred e
2649+
| Pexp_ifthenelse (_, e1, Some e2) -> is_inferred e1 && is_inferred e2
2650+
| _ -> false
2651+
26412652
let rec type_exp ?recarg env (mode : expected_mode) sexp =
26422653
(* We now delegate everything to type_expect *)
26432654
type_expect ?recarg env mode sexp (mk_expected (newvar ()))
@@ -2834,30 +2845,47 @@ and type_expect_
28342845
(Nontail alloc_local) e ty_expected_explained
28352846
| Pexp_apply(sfunct, sargs) ->
28362847
assert (sargs <> []);
2837-
begin_def (); (* one more level for non-returning functions *)
2838-
if !Clflags.principal then begin_def ();
28392848
let funct_mode =
28402849
match mode with
28412850
| Nontail _ -> Alloc_mode.newvar ()
28422851
| Tail _ -> Alloc_mode.heap
28432852
in
2844-
let funct = type_exp env (Nontail funct_mode) sfunct in
2845-
if !Clflags.principal then begin
2846-
end_def ();
2847-
generalize_structure funct.exp_type
2848-
end;
28492853
let rec lower_args seen ty_fun =
28502854
let ty = expand_head env ty_fun in
28512855
if List.memq ty seen then () else
2852-
match ty.desc with
2853-
Tarrow (_l, ty_arg, ty_fun, _com) ->
2854-
(try unify_var env (newvar()) ty_arg with Unify _ -> assert false);
2855-
lower_args (ty::seen) ty_fun
2856-
| _ -> ()
2856+
match ty.desc with
2857+
Tarrow (_l, ty_arg, ty_fun, _com) ->
2858+
(try unify_var env (newvar()) ty_arg
2859+
with Unify _ -> assert false);
2860+
lower_args (ty::seen) ty_fun
2861+
| _ -> ()
2862+
in
2863+
let type_sfunct sfunct =
2864+
begin_def (); (* one more level for non-returning functions *)
2865+
if !Clflags.principal then begin_def ();
2866+
let funct = type_exp env (Nontail funct_mode) sfunct in
2867+
if !Clflags.principal then begin
2868+
end_def ();
2869+
generalize_structure funct.exp_type
2870+
end;
2871+
let ty = instance funct.exp_type in
2872+
end_def ();
2873+
wrap_trace_gadt_instances env (lower_args []) ty;
2874+
funct
2875+
in
2876+
let funct, sargs =
2877+
let funct = type_sfunct sfunct in
2878+
match funct.exp_desc, sargs with
2879+
| Texp_ident (_, _, {val_kind = Val_prim {prim_name = "%revapply"}}),
2880+
[Nolabel, sarg; Nolabel, actual_sfunct]
2881+
when is_inferred actual_sfunct ->
2882+
type_sfunct actual_sfunct, [Nolabel, sarg]
2883+
| Texp_ident (_, _, {val_kind = Val_prim {prim_name = "%apply"}}),
2884+
[Nolabel, actual_sfunct; Nolabel, sarg] ->
2885+
type_sfunct actual_sfunct, [Nolabel, sarg]
2886+
| _ ->
2887+
funct, sargs
28572888
in
2858-
let ty = instance funct.exp_type in
2859-
end_def ();
2860-
wrap_trace_gadt_instances env (lower_args []) ty;
28612889
begin_def ();
28622890
let (args, ty_res) = type_application env loc mode funct sargs in
28632891
end_def ();
@@ -4346,17 +4374,6 @@ and type_argument ?explanation ?recarg env mode sarg ty_expected' ty_expected =
43464374
let ls, tvar = list_labels env ty in
43474375
not tvar && List.for_all ((=) Nolabel) ls
43484376
in
4349-
let rec is_inferred sexp =
4350-
match sexp.pexp_desc with
4351-
| Pexp_apply
4352-
({ pexp_desc = Pexp_extension({txt = "stack"}, PStr []) },
4353-
[Nolabel, _]) -> false
4354-
| Pexp_ident _ | Pexp_apply _ | Pexp_field _ | Pexp_constraint _
4355-
| Pexp_coerce _ | Pexp_send _ | Pexp_new _ -> true
4356-
| Pexp_sequence (_, e) | Pexp_open (_, e) -> is_inferred e
4357-
| Pexp_ifthenelse (_, e1, Some e2) -> is_inferred e1 && is_inferred e2
4358-
| _ -> false
4359-
in
43604377
match expand_head env ty_expected' with
43614378
{desc = Tarrow((Nolabel,marg,mret),ty_arg,ty_res,_); level = lv}
43624379
when is_inferred sarg ->

0 commit comments

Comments
 (0)