Skip to content

Commit 5f196a0

Browse files
committed
try to improve error message
1 parent e779844 commit 5f196a0

File tree

4 files changed

+35
-13
lines changed

4 files changed

+35
-13
lines changed

compiler/ml/error_message_utils.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ type type_clash_context =
9494
| AssertCondition
9595
| IfReturn
9696
| SwitchReturn
97+
| LetUnwrapReturn
9798
| TryReturn
9899
| StringConcat
99100
| ComparisonOperator
@@ -126,6 +127,7 @@ let context_to_string = function
126127
| Some ComparisonOperator -> "ComparisonOperator"
127128
| Some IfReturn -> "IfReturn"
128129
| Some Await -> "Await"
130+
| Some LetUnwrapReturn -> "LetUnwrapReturn"
129131
| None -> "None"
130132
131133
let fprintf = Format.fprintf
@@ -158,6 +160,9 @@ let error_expected_type_text ppf type_clash_context =
158160
| Some ComparisonOperator ->
159161
fprintf ppf "But it's being compared to something of type:"
160162
| Some SwitchReturn -> fprintf ppf "But this switch is expected to return:"
163+
| Some LetUnwrapReturn ->
164+
fprintf ppf
165+
"But this @{<info>let?@} is used in a context expecting the type:"
161166
| Some TryReturn -> fprintf ppf "But this try/catch is expected to return:"
162167
| Some WhileCondition ->
163168
fprintf ppf "But a @{<info>while@} loop condition must always be of type:"
@@ -308,6 +313,11 @@ let print_extra_type_clash_help ~extract_concrete_typedecl ~env loc ppf
308313
"\n\n\
309314
\ All branches in a @{<info>switch@} must return the same type.@,\
310315
To fix this, change your branch to return the expected type."
316+
| Some LetUnwrapReturn, _ ->
317+
fprintf ppf
318+
"\n\n\
319+
\ @{<info>let?@} can only be used in a context that expects \
320+
@{<info>option@} or @{<info>result@}."
311321
| Some TryReturn, _ ->
312322
fprintf ppf
313323
"\n\n\

compiler/ml/typecore.ml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,12 +2475,21 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
24752475
(* Note: val_caselist = [] and exn_caselist = [], i.e. a fully
24762476
empty pattern matching can be generated by Camlp4 with its
24772477
revised syntax. Let's accept it for backward compatibility. *)
2478+
let call_context =
2479+
if
2480+
Ext_list.exists sexp.pexp_attributes (fun ({txt}, _) ->
2481+
match txt with
2482+
| "let.unwrap" -> true
2483+
| _ -> false)
2484+
then `LetUnwrap
2485+
else `Switch
2486+
in
24782487
let val_cases, partial =
2479-
type_cases ~call_context:`Switch env arg.exp_type ty_expected true loc
2488+
type_cases ~call_context env arg.exp_type ty_expected true loc
24802489
val_caselist
24812490
in
24822491
let exn_cases, _ =
2483-
type_cases ~call_context:`Switch env Predef.type_exn ty_expected false loc
2492+
type_cases ~call_context env Predef.type_exn ty_expected false loc
24842493
exn_caselist
24852494
in
24862495
re
@@ -3864,8 +3873,9 @@ and type_statement ~context env sexp =
38643873
38653874
(* Typing of match cases *)
38663875
3867-
and type_cases ~(call_context : [`Switch | `Function | `Try]) ?in_function env
3868-
ty_arg ty_res partial_flag loc caselist : _ * Typedtree.partial =
3876+
and type_cases ~(call_context : [`LetUnwrap | `Switch | `Function | `Try])
3877+
?in_function env ty_arg ty_res partial_flag loc caselist :
3878+
_ * Typedtree.partial =
38693879
(* ty_arg is _fully_ generalized *)
38703880
let patterns = List.map (fun {pc_lhs = p} -> p) caselist in
38713881
let contains_polyvars = List.exists contains_polymorphic_variant patterns in
@@ -3983,6 +3993,7 @@ and type_cases ~(call_context : [`Switch | `Function | `Try]) ?in_function env
39833993
(match call_context with
39843994
| `Switch -> Some SwitchReturn
39853995
| `Try -> Some TryReturn
3996+
| `LetUnwrap -> Some LetUnwrapReturn
39863997
| `Function -> None)
39873998
?in_function ext_env sexp ty_res'
39883999
in
Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11

22
We've found a bug for you!
3-
/.../fixtures/let_unwrap_return_type_mismatch.res:4:8-14
3+
/.../fixtures/let_unwrap_return_type_mismatch.res:6:8-14
44

5-
2 │
6-
3 │ let fn = (): int => {
7-
4 │ let? Some(x) = None
8-
5 │ 42
9-
6 │ }
5+
4 │
6+
5 │ let fn = (): int => {
7+
6 │ let? Some(x) = None
8+
7 │ 42
9+
8 │ }
1010

1111
This has type: option<'a>
12-
But this switch is expected to return: int
12+
But this let? is used in a context expecting the type: int
1313

14-
All branches in a switch must return the same type.
15-
To fix this, change your branch to return the expected type.
14+
let? can only be used in a context that expects option or result.

tests/build_tests/super_errors/fixtures/let_unwrap_return_type_mismatch.res

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
@@config({flags: ["-enable-experimental", "LetUnwrap"]})
22

3+
let x = Some(1)
4+
35
let fn = (): int => {
46
let? Some(x) = None
57
42

0 commit comments

Comments
 (0)