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

Strange behavior of exhaustive record copy with disambiguation #7211

Closed
vicuna opened this Issue Apr 5, 2016 · 1 comment

Comments

Projects
None yet
2 participants
@vicuna
Copy link
Collaborator

vicuna commented Apr 5, 2016

Original bug ID: 7211
Reporter: pcouderc
Assigned to: @gasche
Status: resolved (set by @gasche on 2016-11-12T15:23:57Z)
Resolution: fixed
Priority: low
Severity: minor
Version: 4.02.3
Target version: 4.03.1+dev
Fixed in version: 4.05.0 +dev/beta1/beta2/beta3/rc1
Category: typing
Duplicate of: #6608
Monitored by: @gasche @hcarty

Bug description

When copying a record and redefining all the fields, the compiler gives the following warning:
Warning 23: all the fields are explicitly listed in this record:
the 'with' clause is useless.

For example:

type t = { v : int };;

type t = { v : int; }

let x = { v = 0 };;

val x : t = {v = 0}

let y = {x with v = 1 };;

Warning 23: all the fields are explicitly listed in this record:
the 'with' clause is useless.
val y : t = {v = 1}

Surprisingly, the following value is accepted:

let z = { "What?" with v = 2 };;

Warning 23: all the fields are explicitly listed in this record:
the 'with' clause is useless.
val z : t = {v = 2}

It is surprising, but it is possible thanks to the fields disambiguation. It will not break programs since the string will not be accessed.
However, the following program is not accepted:

type t' = { u : int };;

type t' = { u : int; }

let x' = { u = 0 };;

val x' : t' = {u = 0}

let y' = { x' with v = 2 };;

Error: This record expression is expected to have type t'
The field v does not belong to type t'

A record of another type is not accepted as the unused copy, even if this copied record will not be accessed.

Finally, one can write the following function:

let f x = { x with v = 42 };;

Warning 23: all the fields are explicitly listed in this record:
the 'with' clause is useless.
val f : 'a -> t =

It will be polymorphic, so it will accept any other record type as argument.
On a "theoretic" point of view, it breaks the subject reduction I guess, but it will not actually break programs since the "copied record" is never accessed for the copy.

However, one problem is that it can break APIs of modules that does not have an explicit signature: if the previous function is exported, it can be used polymorphically and becomes monomorphic if the record is extended with new fields. If the user of the module use it with any argument with a different type than the record, his code will not typecheck anymore.

Additional information

Works since 4.00.

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

vicuna commented Nov 12, 2016

Comment author: @gasche

This is a (nice and more detailed) report of the same issue as #6608, which has now being resolved in trunk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.