Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ground coercion is not composable #13120

Open
samsa1 opened this issue Apr 25, 2024 · 1 comment
Open

Ground coercion is not composable #13120

samsa1 opened this issue Apr 25, 2024 · 1 comment

Comments

@samsa1
Copy link
Contributor

samsa1 commented Apr 25, 2024

I've been looking at type coercion and found some weird behavior.

In the example below, test1 is of type 'a -> (int * 'a) as expected, however test2 is ill typed.

module M : sig
  type t = private int
  val el : t
end = struct
  type t = int
  let el = 0
end

let test1 (x : 'a) = ((M.el :> int), (x :> 'a))

let test2 (x : 'a) = ((M.el, x) :> (int * 'a))

The error message is

File "test.ml", line 11, characters 22-31:
11 | let test2 (x : 'a) = ((M.el, x) :> (int * 'a))
                           ^^^^^^^^^
Error: This expression cannot be coerced to type int * 'a; it has type
         M.t * 'a
       but is here used with type int * 'a
       Type M.t is not compatible with type int

The reason behind this is that coercion with closed types is strictly more expressive than with types containing a free type variable due to the following line in typing/typecore.ml :

ocaml/typing/typecore.ml

Lines 4358 to 4359 in 564b2db

| _ when free_variables ~env arg_type = []
&& free_variables ~env ty' = [] ->

I tried removing this guard and launching the testsuite, but this is never tested in the testsuite.
Is the behavior of the example above expected ? If so shouldn't we document this behavior and add a related test ? Or is this a bug ?

PS : Similar problem with a first class module instead of a private type

@garrigue
Copy link
Contributor

This is the intended behavior, and this is documented in the reference manual, section 7.7 (coercions):

As an exception to the above algorithm, if both the inferred type of expr and typ are ground (i.e. do not contain type variables), the former operator behaves as the latter one, taking the inferred type of expr as typ1. In case of failure with the former operator, the latter one should be used.

Adding a related test may be a good idea still.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants