From 1b46dbe329e5b3b8ed47038a87990a4cd28e0d29 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Mon, 11 Dec 2023 09:55:40 +0100 Subject: [PATCH] Add support for typer coercion for invariant type arguments such as array payloads. If type `t<'a>` is invariant in `'a` allow type coercion from `t ` to `t` if both `t1` can be coerced to `t2` and `t2` can be coerced to `t1`, which must imply that the runtime representations are the same. --- jscomp/ml/ctype.ml | 10 ++++++++-- jscomp/test/Coercion.js | 5 +++++ jscomp/test/Coercion.res | 8 ++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/jscomp/ml/ctype.ml b/jscomp/ml/ctype.ml index bb5154738a..7dd114fed8 100644 --- a/jscomp/ml/ctype.ml +++ b/jscomp/ml/ctype.ml @@ -3939,8 +3939,14 @@ let rec subtype_rec env trace t1 t2 cstrs = let (co, cn) = Variance.get_upper v in if co then if cn then - (trace, newty2 t1.level (Ttuple[t1]), - newty2 t2.level (Ttuple[t2]), !univar_pairs) :: cstrs + (* Invariant type argument: check both ways *) + if + subtype_rec env ((t1, t2)::trace) t1 t2 [] = [] && + subtype_rec env ((t2, t1)::trace) t2 t1 [] = [] then + cstrs + else + (trace, newty2 t1.level (Ttuple[t1]), + newty2 t2.level (Ttuple[t2]), !univar_pairs) :: cstrs else subtype_rec env ((t1, t2)::trace) t1 t2 cstrs else if cn then subtype_rec env ((t2, t1)::trace) t2 t1 cstrs diff --git a/jscomp/test/Coercion.js b/jscomp/test/Coercion.js index 8f99712b85..7e2ca2ca8b 100644 --- a/jscomp/test/Coercion.js +++ b/jscomp/test/Coercion.js @@ -2,10 +2,15 @@ 'use strict'; +function foo(x) { + return x; +} + var x = 1; var xx = 1; exports.x = x; exports.xx = xx; +exports.foo = foo; /* No side effect */ diff --git a/jscomp/test/Coercion.res b/jscomp/test/Coercion.res index 76e0eb8700..d7c89f7b54 100644 --- a/jscomp/test/Coercion.res +++ b/jscomp/test/Coercion.res @@ -1,3 +1,11 @@ let x = 1 let xx = (x :> float) + +type r1 = {x:int} +type r2 = {x:int} + +type t1 = array +type t2 = array + +let foo = (x: t1) => { x :> t2 }