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
All-float records and abstractions don't mix #4584
Comments
Comment author: @alainfrisch 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 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.) |
Comment author: @alainfrisch (Related to #4423) |
Comment author: @xavierleroy 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 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. |
Comment author: @alainfrisch Less confusing error message. |
Original bug ID: 4584
Reporter: @mmottl
Assigned to: @alainfrisch
Status: closed (set by @xavierleroy on 2013-08-31T10:43:55Z)
Resolution: duplicate
Priority: normal
Severity: minor
Version: 3.10.2
Category: ~DO NOT USE (was: OCaml general)
Duplicate of: #4423
Monitored by: BenediktGrundmann sweeks till "Julien Signoles" @Chris00 @oandrieu @alainfrisch @mmottl
Bug description
Consider the following file foo.ml:
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 foo.ml 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.
The text was updated successfully, but these errors were encountered: