| Anonymous | Login | Signup for a new account | 2013-05-24 18:57 CEST | ![]() |
| Main | My View | View Issues | Change Log | Roadmap |
| View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | |||||||||||
| ID | Project | Category | View Status | Date Submitted | Last Update | |||||||
| 0004584 | OCaml | OCaml general | public | 2008-07-18 20:31 | 2011-05-19 10:10 | |||||||
| Reporter | mottl | |||||||||||
| Assigned To | frisch | |||||||||||
| Priority | normal | Severity | minor | Reproducibility | always | |||||||
| Status | resolved | Resolution | duplicate | |||||||||
| Platform | OS | OS Version | ||||||||||
| Product Version | 3.10.2 | |||||||||||
| Target Version | Fixed in Version | |||||||||||
| Summary | 0004584: All-float records and abstractions don't mix | |||||||||||
| 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. | |||||||||||
| Tags | No tags attached. | |||||||||||
| Attached Files | ||||||||||||
Relationships |
||||||
|
||||||
Notes |
|
|
(0004538) 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 end 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.) |
|
(0004539) frisch (developer) 2008-07-24 08:34 |
(Related to 0004423) |
|
(0004574) 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. |
|
(0005911) 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 |
| Copyright © 2000 - 2011 MantisBT Group |