From 72f35ef9adcdb79a4ca83666d9d2b40738987ca1 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Wed, 19 Oct 2022 15:34:17 +0100 Subject: [PATCH 1/2] Fix issue where exhaustiveness check for pattern matching char was not working Fixes https://github.com/rescript-lang/rescript-compiler/issues/5557 Fixes https://github.com/rescript-lang/rescript-compiler/issues/5743 Exhaustiveness check for pattern matching relies on checking that the pattern does not lead to a type error. Since char constants are represented internally as int, this causes an internal type error when processing patterns of the form 'x', where the constant is represented as `Pconst_integer` but the expected type is `char`. This PR intercepts this situation and changes the expected type to `int`. A cleaner solution would be to represent chars differently (but we can't change the AST), or make it official that char and int is the same type (and lose some abstraction). --- CHANGELOG.md | 4 ++++ jscomp/ml/typecore.ml | 5 +++++ lib/4.06.1/unstable/js_compiler.ml | 5 +++++ lib/4.06.1/unstable/js_playground_compiler.ml | 5 +++++ lib/4.06.1/whole_compiler.ml | 5 +++++ 5 files changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f238068159..71c7d3be11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ # 10.1.0-rc.3 +#### :bug: Bug Fix + +- Fix issue where exhaustiveness check for pattern matching char was not working https://github.com/rescript-lang/rescript-compiler/issues/5557 + # 10.1.0-rc.2 #### :bug: Bug Fix diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 012cdd765c..fb165408bf 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -1350,6 +1350,11 @@ let partial_pred ~lev ?mode ?explode env expected_ty constrs labels p = let state = save_state env in try reset_pattern None true; + let expected_ty = match p.ppat_desc, expected_ty.desc with + | Ppat_constant (Pconst_integer _ ), Tconstr (path, [], _) when Path.same path Predef.path_char -> + (* Constants such as 'foo' are represented as Pconst_integer but expected to have type char *) + Predef.type_int + | _ -> expected_ty in let typed_p = Ctype.with_passive_variants (type_pat ~allow_existentials:true ~lev diff --git a/lib/4.06.1/unstable/js_compiler.ml b/lib/4.06.1/unstable/js_compiler.ml index 0e6879f617..cb269fde98 100644 --- a/lib/4.06.1/unstable/js_compiler.ml +++ b/lib/4.06.1/unstable/js_compiler.ml @@ -40301,6 +40301,11 @@ let partial_pred ~lev ?mode ?explode env expected_ty constrs labels p = let state = save_state env in try reset_pattern None true; + let expected_ty = match p.ppat_desc, expected_ty.desc with + | Ppat_constant (Pconst_integer _ ), Tconstr (path, [], _) when Path.same path Predef.path_char -> + (* Constants such as 'foo' are represented as Pconst_integer but expected to have type char *) + Predef.type_int + | _ -> expected_ty in let typed_p = Ctype.with_passive_variants (type_pat ~allow_existentials:true ~lev diff --git a/lib/4.06.1/unstable/js_playground_compiler.ml b/lib/4.06.1/unstable/js_playground_compiler.ml index 314e28560a..6c1a00584a 100644 --- a/lib/4.06.1/unstable/js_playground_compiler.ml +++ b/lib/4.06.1/unstable/js_playground_compiler.ml @@ -40301,6 +40301,11 @@ let partial_pred ~lev ?mode ?explode env expected_ty constrs labels p = let state = save_state env in try reset_pattern None true; + let expected_ty = match p.ppat_desc, expected_ty.desc with + | Ppat_constant (Pconst_integer _ ), Tconstr (path, [], _) when Path.same path Predef.path_char -> + (* Constants such as 'foo' are represented as Pconst_integer but expected to have type char *) + Predef.type_int + | _ -> expected_ty in let typed_p = Ctype.with_passive_variants (type_pat ~allow_existentials:true ~lev diff --git a/lib/4.06.1/whole_compiler.ml b/lib/4.06.1/whole_compiler.ml index 396eb85143..17c444aad6 100644 --- a/lib/4.06.1/whole_compiler.ml +++ b/lib/4.06.1/whole_compiler.ml @@ -216688,6 +216688,11 @@ let partial_pred ~lev ?mode ?explode env expected_ty constrs labels p = let state = save_state env in try reset_pattern None true; + let expected_ty = match p.ppat_desc, expected_ty.desc with + | Ppat_constant (Pconst_integer _ ), Tconstr (path, [], _) when Path.same path Predef.path_char -> + (* Constants such as 'foo' are represented as Pconst_integer but expected to have type char *) + Predef.type_int + | _ -> expected_ty in let typed_p = Ctype.with_passive_variants (type_pat ~allow_existentials:true ~lev From f684c33ae20f7714dcc5ef512640639bbc60098f Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Wed, 19 Oct 2022 16:09:59 +0100 Subject: [PATCH 2/2] comment --- jscomp/ml/typecore.ml | 2 +- lib/4.06.1/unstable/js_compiler.ml | 2 +- lib/4.06.1/unstable/js_playground_compiler.ml | 2 +- lib/4.06.1/whole_compiler.ml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index fb165408bf..4dbc11b7c7 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -1352,7 +1352,7 @@ let partial_pred ~lev ?mode ?explode env expected_ty constrs labels p = reset_pattern None true; let expected_ty = match p.ppat_desc, expected_ty.desc with | Ppat_constant (Pconst_integer _ ), Tconstr (path, [], _) when Path.same path Predef.path_char -> - (* Constants such as 'foo' are represented as Pconst_integer but expected to have type char *) + (* Constants such as 'x' are represented as Pconst_integer but expected to have type char *) Predef.type_int | _ -> expected_ty in let typed_p = diff --git a/lib/4.06.1/unstable/js_compiler.ml b/lib/4.06.1/unstable/js_compiler.ml index cb269fde98..d4dca29dfe 100644 --- a/lib/4.06.1/unstable/js_compiler.ml +++ b/lib/4.06.1/unstable/js_compiler.ml @@ -40303,7 +40303,7 @@ let partial_pred ~lev ?mode ?explode env expected_ty constrs labels p = reset_pattern None true; let expected_ty = match p.ppat_desc, expected_ty.desc with | Ppat_constant (Pconst_integer _ ), Tconstr (path, [], _) when Path.same path Predef.path_char -> - (* Constants such as 'foo' are represented as Pconst_integer but expected to have type char *) + (* Constants such as 'x' are represented as Pconst_integer but expected to have type char *) Predef.type_int | _ -> expected_ty in let typed_p = diff --git a/lib/4.06.1/unstable/js_playground_compiler.ml b/lib/4.06.1/unstable/js_playground_compiler.ml index 6c1a00584a..22e7d91b52 100644 --- a/lib/4.06.1/unstable/js_playground_compiler.ml +++ b/lib/4.06.1/unstable/js_playground_compiler.ml @@ -40303,7 +40303,7 @@ let partial_pred ~lev ?mode ?explode env expected_ty constrs labels p = reset_pattern None true; let expected_ty = match p.ppat_desc, expected_ty.desc with | Ppat_constant (Pconst_integer _ ), Tconstr (path, [], _) when Path.same path Predef.path_char -> - (* Constants such as 'foo' are represented as Pconst_integer but expected to have type char *) + (* Constants such as 'x' are represented as Pconst_integer but expected to have type char *) Predef.type_int | _ -> expected_ty in let typed_p = diff --git a/lib/4.06.1/whole_compiler.ml b/lib/4.06.1/whole_compiler.ml index 17c444aad6..0ec973290c 100644 --- a/lib/4.06.1/whole_compiler.ml +++ b/lib/4.06.1/whole_compiler.ml @@ -216690,7 +216690,7 @@ let partial_pred ~lev ?mode ?explode env expected_ty constrs labels p = reset_pattern None true; let expected_ty = match p.ppat_desc, expected_ty.desc with | Ppat_constant (Pconst_integer _ ), Tconstr (path, [], _) when Path.same path Predef.path_char -> - (* Constants such as 'foo' are represented as Pconst_integer but expected to have type char *) + (* Constants such as 'x' are represented as Pconst_integer but expected to have type char *) Predef.type_int | _ -> expected_ty in let typed_p =