Skip to content

Commit 333c71d

Browse files
committed
Fix issue with overlapping array and object in untagged variants.
1 parent a66e2d3 commit 333c71d

5 files changed

+49
-16
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
- Make "rescript format" work with node 10 again and set minimum required node version to 10 in package.json. https://github.com/rescript-lang/rescript-compiler/pull/6186
3131
- Fix partial application for uncurried functions with labeled args https://github.com/rescript-lang/rescript-compiler/pull/6198
3232
- Add error messages for dangling doc comments/attributes and mutable in record type definition. https://github.com/rescript-lang/rescript-compiler/pull/6206
33+
- Fix issue with overlapping array and object in untagged variants https://github.com/rescript-lang/rescript-compiler/pull/6219
3334

3435
# 11.0.0-alpha.4
3536

jscomp/core/lam_compile.ml

+9-8
Original file line numberDiff line numberDiff line change
@@ -625,11 +625,11 @@ and use_compile_literal_cases table ~(get_tag : _ -> Ast_untagged_variants.tag o
625625
) table (Some [])
626626
and compile_cases
627627
?(untagged=false) ~cxt ~(switch_exp : E.t) ?(default = NonComplete)
628-
?(get_tag = fun _ -> None) cases : initialization =
628+
?(get_tag = fun _ -> None) ?(block_cases=[]) cases : initialization =
629629
match use_compile_literal_cases cases ~get_tag with
630630
| Some string_cases ->
631631
if untagged
632-
then compile_untagged_cases ~cxt ~switch_exp ~default string_cases
632+
then compile_untagged_cases ~cxt ~switch_exp ~block_cases ~default string_cases
633633
else compile_string_cases ~cxt ~switch_exp ~default string_cases
634634
| None ->
635635
cases |> compile_general_cases
@@ -688,13 +688,13 @@ and compile_switch (switch_arg : Lam.t) (sw : Lam.lambda_switch)
688688
block
689689
@
690690
if sw_consts_full && sw_consts = [] then
691-
compile_cases
691+
compile_cases ~block_cases
692692
~untagged ~cxt
693693
~switch_exp:(if untagged then e else E.tag ~name:tag_name e)
694694
~default:sw_blocks_default
695695
~get_tag:get_block_tag sw_blocks
696696
else if sw_blocks_full && sw_blocks = [] then
697-
compile_cases ~cxt ~switch_exp:e ~default:sw_num_default ~get_tag:get_const_tag sw_consts
697+
compile_cases ~cxt ~switch_exp:e ~block_cases ~default:sw_num_default ~get_tag:get_const_tag sw_consts
698698
else
699699
(* [e] will be used twice *)
700700
let dispatch e =
@@ -706,11 +706,12 @@ and compile_switch (switch_arg : Lam.t) (sw : Lam.lambda_switch)
706706
else
707707
E.is_int_tag ~has_null_undefined_other:(has_null_undefined_other sw_names) e in
708708
S.if_ is_a_literal_case
709-
(compile_cases ~cxt ~switch_exp:e ~default:sw_num_default ~get_tag:get_const_tag sw_consts)
709+
(compile_cases ~cxt ~switch_exp:e ~block_cases ~default:sw_num_default ~get_tag:get_const_tag sw_consts)
710710
~else_:
711711
(compile_cases
712712
~untagged ~cxt
713713
~switch_exp:(if untagged then e else E.tag ~name:tag_name e)
714+
~block_cases
714715
~default:sw_blocks_default
715716
~get_tag:get_block_tag sw_blocks)
716717
in
@@ -749,13 +750,13 @@ and compile_string_cases ~cxt ~switch_exp ~default cases: initialization =
749750
S.string_switch ?default ?declaration e clauses)
750751
~switch_exp
751752
~default
752-
and compile_untagged_cases ~cxt ~switch_exp ~default cases =
753+
and compile_untagged_cases ~cxt ~switch_exp ~default ~block_cases cases =
753754
let mk_eq (i : Ast_untagged_variants.tag_type option) x j y =
754755
let check = match i, j with
755756
| Some tag_type, _ ->
756-
Ast_untagged_variants.DynamicChecks.add_runtime_type_check ~tag_type (Expr x) (Expr y)
757+
Ast_untagged_variants.DynamicChecks.add_runtime_type_check ~tag_type ~block_cases (Expr x) (Expr y)
757758
| _, Some tag_type ->
758-
Ast_untagged_variants.DynamicChecks.add_runtime_type_check ~tag_type (Expr y) (Expr x)
759+
Ast_untagged_variants.DynamicChecks.add_runtime_type_check ~tag_type ~block_cases (Expr y) (Expr x)
759760
| _ ->
760761
Ast_untagged_variants.DynamicChecks.(==) (Expr x) (Expr y)
761762
in

jscomp/ml/ast_untagged_variants.ml

+9-3
Original file line numberDiff line numberDiff line change
@@ -328,11 +328,17 @@ module DynamicChecks = struct
328328
else (* (undefiled + other) || other *)
329329
typeof e != object_
330330

331-
let add_runtime_type_check ~tag_type x y = match tag_type with
331+
let add_runtime_type_check ~tag_type ~(block_cases: block_type list) x y =
332+
let has_array() = Ext_list.exists block_cases (fun t -> t = ArrayType) in
333+
match tag_type with
332334
| Untagged IntType
333335
| Untagged StringType
334-
| Untagged FloatType
335-
| Untagged ObjectType -> typeof y == x
336+
| Untagged FloatType -> typeof y == x
337+
| Untagged ObjectType ->
338+
if has_array() then
339+
typeof y == x &&& not (is_array y)
340+
else
341+
typeof y == x
336342
| Untagged ArrayType -> is_array y
337343
| Untagged UnknownType ->
338344
(* This should not happen because unknown must be the only non-literal case *)

jscomp/test/UntaggedVariants.js

+13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/test/UntaggedVariants.res

+17-5
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,25 @@ module OverlapObject = {
239239
module RecordIsObject = {
240240
// @unboxed
241241
// this is not allowed
242-
type r = {x:int}
242+
type r = {x: int}
243243

244244
@unboxed
245-
type t = | Array(array<int>) | Record(r)
245+
type t = Array(array<int>) | Record(r)
246246

247-
let classify = v => switch v {
247+
let classify = v =>
248+
switch v {
248249
| Record({x}) => x
249250
| Array(a) => a[0]
250-
}
251-
}
251+
}
252+
}
253+
254+
module ArrayAndObject = {
255+
@unboxed
256+
type t = Record({x: int}) | Array(array<int>)
257+
258+
let classify = v =>
259+
switch v {
260+
| Record({x}) => x
261+
| Array(a) => a[0]
262+
}
263+
}

0 commit comments

Comments
 (0)