Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0005834OCaml~DO NOT USE (was: OCaml general)public2012-11-19 07:002015-12-11 19:08
Assigned Togasche 
StatusclosedResolutionno change required 
PlatformOSMac OS XOS Version10.7.5
Product Version4.00.1 
Target VersionFixed in Version 
Summary0005834: Confused by Marshal type safety
DescriptionThis low-priority bug report shows more my misunderstanding of the Marshal.from_channel function rather than a problem with OCaml, but I wanted to register it anyway in case type safety could be added to the Marshal module as a feature in future.

If I (unwisely) send an extra parameter to a function that contains a command to un-marshall some data, and also fail to follow the instructions in the manual about explicitly setting the type of the data, then the compiler gives a warning ("Warning 20: this argument will not be used by the function."), but at run time the program crashes with a "Bus error: 10".

This happens when using both ocamlopt and ocamlc

If I explicitly specify the return type then the program gives the expected behaviour, and refuses to compile, giving: "Error: This function is applied to too many arguments".
Steps To Reproducelet loadData filename =
  let channel = open_in_bin filename in
  let data = Marshal.from_channel channel in
  close_in channel;
let _ =
  let _ = loadData "test.marshal" (* extra parameter: *) 1 in
TagsNo tags attached.
Attached Files

- Relationships

-  Notes
gasche (developer)
2012-11-19 10:05

The current behavior of Marshal with respect to typing is rather simple: functions of the Marshal module have a type of the form (foo -> 'a), where foo is the input type (string, in_channel, etc.). This means that their return type is fully polymorphic, just as the return type of (raise : exn -> 'a) for example.

You can do anything with a value of such a type and the type-checker can't stop you. The advice to add an explicit type annotation is precisely there to refine the static information of the program and allow for more static verification.

About warning 20: when an expression produced has a fully polymorphic type such as ('a), then in particular you can instantiate it to a function type of the form ('b -> 'c). But if it was produced without magic (Marshal or Obj) you know, statically, that this function will not use its argument. Indeed, to use its argument a function must evaluates to something of the form (fun foo -> ...), and therefore be type-checked as a function type (_ -> _) rather than a fully polymorphic type. Warning 20 is there to tell the programmer: "you're doing something weird by trying to pass an argument to something that I know isn't a regular function".

# let rec loop arg = loop arg;;
val loop : 'a -> 'b = <fun>
# loop () 1;;
Warning 20: this argument will not be used by the function.
# (raise Exit) 1;;
Warning 20: this argument will not be used by the function.
Exception: Pervasives.Exit.

Of course, in the context of Marshal, this warning isn't always appropriate because it may be the case that what you unmarshalled really is a function. It's only a way for the compiler to tell you it doesn't have any static knowledge about this function -- so annotating it with some type information would be a good idea, if only to provide better static information about the function return type.
To sum up, this warning is useful in other circumstances and doesn't hurt in this case. Besides it would be technically difficult/complicated to special-case the result of unmarshaling (that would require a non-local test) to disable the warning. I don't expect this behavior to change in a medium-term future.

- Issue History
Date Modified Username Field Change
2012-11-19 07:00 warwick New Issue
2012-11-19 10:05 gasche Note Added: 0008532
2012-11-19 10:05 gasche Status new => resolved
2012-11-19 10:05 gasche Resolution open => no change required
2012-11-19 10:05 gasche Assigned To => gasche
2015-12-11 19:08 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