Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0004584OCaml~DO NOT USE (was: OCaml general)public2008-07-18 20:312013-08-31 12:43
Assigned Tofrisch 
PlatformOSOS Version
Product Version3.10.2 
Target VersionFixed in Version 
Summary0004584: All-float records and abstractions don't mix
DescriptionConsider the following file

  type t = float
  type u = { t : t }

together with the following foo.mli:

  type t
  type u = { t : t }

Trying to compile these will give the following very unintuitive error:

  The implementation does not match the interface foo.cmi:
  Type declarations do not match:
    type u = { t : t; }
  is not included in
    type u = { t : t; }

Replacing "float" with e.g. "unit" will make this module compile just fine. The reason is quite obviously the well-known fact that OCaml uses a more efficient unboxed representation for float records.

However, this kind of error message is hopelessly confusing, especially when it happens in the presence of nested modules, where it may not be easy for humans to see that they are dealing with an all-float record. Furthermore, OCaml seems slightly inconsistent here, because float arrays, too, are represented in an unboxed way, but using an array instead of a record in the above code seems to work fine with floats.

It would be great if the compiler could use the same approach for dealing with all-float records as it already does with arrays when accessing elements, i.e. if the compiler cannot prove at compile time whether or not some record is all-floats, it will have to generate code to perform a runtime check. In most cases the compiler will be able to avoid generating such a check anyway. At least giving more details in the error message why unification fails might otherwise be helpful.
TagsNo tags attached.
Attached Files

- Relationships
duplicate of 0004423closedfrisch Amelioration message d'erreur pour les enregistrements de floats 

-  Notes
frisch (developer)
2008-07-24 08:32

I agree the situation is not satisfying and that at least the error message should be improved. But I would not like to see a solution arrays implemented for records. Note that the solution would be more complicated than for arrays anyway, because it might be needed to check several fields when the record is created (there might be several type arguments to the record's definition); also, supporting the {... with ...} notation efficiently would not be trivial.

Actually, one could argue that the solution for arrays is not itself very satisfying: any polymorphic function on arrays suffers from runtime checks, and we loose the nice property that reading from an array does not allocate memory (and thus cannot trigger the GC, for instance; the same problem holds for all-floats records, btw). Also, it adds constraints to the way values are represented and complexity to the runtime system: for instance, because of float arrays, it not possible to represent a forced "float lazy" as a float in memory.

For records, I think a good solution would be to add a syntactic marker to the record definition to indicate that all fields are unboxed floats (the fact that fields are indeed floats is checked when the record type is declared). I don't think that automatically unboxing a parametrized record type when parameters happens to be floats by coincidence actually matters in real code (for intensive numerical code, we would probably use other data structures anyway or at least be willing to define custom record types).

For instance, one could write:

module M: sig
  type t
  type s = {x:t; y:float} as float
end = struct
  type t = float
  type s = {x:t; y:t} as float

and removing any of the two "as float" annotation would yield a type-error.

(Implicitly, the signature implies that t is a float but we cannot use this information.)
frisch (developer)
2008-07-24 08:34

(Related to 0004423)
xleroy (administrator)
2008-08-06 11:06

I wholeheartedly agree that the error message should be improved, and also for other cases of mismatch between two type declarations. I'm not sure it can be done for release 3.11 but I'll look into it.

The current approach to data representation for records isn't perfect, but I believe it is the least of several evils. Extending the trick used for arrays is problematic as Alain said.

The "private type abbreviations" feature of 3.11 can alleviate this issue. If you give the interface foo.mli as

  type t = private float
  type u = { t: t }

the compiler "sees" just enough in the definition of "t" to select the proper representation of "u" within clients of Foo. Yet, most of the benefits of type abstraction are preserved.
frisch (developer)
2011-05-19 10:10

Less confusing error message.

- Issue History
Date Modified Username Field Change
2008-07-18 20:31 mottl New Issue
2008-07-24 08:32 frisch Note Added: 0004538
2008-07-24 08:34 frisch Note Added: 0004539
2008-08-01 10:52 xleroy Relationship added related to 0004423
2008-08-06 11:06 xleroy Note Added: 0004574
2008-08-06 11:06 xleroy Status new => acknowledged
2011-05-19 10:10 frisch Note Added: 0005911
2011-05-19 10:10 frisch Relationship replaced duplicate of 0004423
2011-05-19 10:10 frisch Duplicate ID 0 => 4423
2011-05-19 10:10 frisch Status acknowledged => resolved
2011-05-19 10:10 frisch Resolution open => duplicate
2011-05-19 10:10 frisch Assigned To => frisch
2013-08-31 12:43 xleroy Status resolved => closed
2017-02-23 16:36 doligez Category OCaml general => -OCaml general
2017-03-03 17:55 doligez Category -OCaml general => -(deprecated) general
2017-03-03 18:01 doligez Category -(deprecated) general => ~deprecated (was: OCaml general)
2017-03-06 17:04 doligez Category ~deprecated (was: OCaml general) => ~DO NOT USE (was: OCaml general)

Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker