Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0005748OCamltypingpublic2012-08-31 22:252017-03-07 14:40
ReporterMartin Jambon 
Assigned Togarrigue 
StatusclosedResolutionno change required 
PlatformanyOSOS Version
Product Version4.00.0 
Target VersionlaterFixed in Version 
Summary0005748: anonymous functions with optional arguments
DescriptionIn OCaml 4.00, anonymous functions with optional arguments can no longer be passed to a higher order function that doesn't know expect optional arguments. Here is an example:

let f g = g () ;;

(* works in 3.12 and 4.00 *)
let g = fun ?opt () -> () in
f g

Here is what no longer works in OCaml 4.00.0 but used to work in 3.12.1:

# f (fun ?opt () -> ()) ;;
Error: This function should have type unit -> 'a
       but its first argument is labelled ~?opt

This breaks some of our code where the anonymous function is generated by a Camlp4 macro.
TagsNo tags attached.
Attached Files

- Relationships
related to 0006352closedgarrigue Automatic removal of optional arguments and sequencing 

-  Notes
garrigue (manager)
2012-09-04 06:12

Repeating the message of the caml-list (feedback request at the end):

OCaml 4.00 is much more agressive in propagating expected types when typing
expressions. Unfortunately, there was a conflict between this upward propagation,
and the somehow adhoc behaviour which removes optional arguments from
a function passed as argument to a function or record/variant constructor not expecting
optional arguments.

Specifically, this is this behavior:

val f : (unit -> unit) -> unit
val g : ?x:int -> ?y:bool -> unit -> unit

let () = f g

This code triggers automatic discarding of the optional arguments of g,
so that the type matches the expected one.

But for this we need to first infer the type of the argument, to see that
it doesn't match the expected one.

I was not aware that this feature was widely used, and the behavior in 4.00.0
is to restrict this feature to expressions where upward propagation doesn't
make sense anyway:
* identifiers
* function applications
* message sending
* record field extraction
* wrapping of "let open" around any of those

An inline function doesn't enter this category.

I'm pondering what to do about this.
Since this feature is described in the tutorial part of the reference manual, I suppose this
qualifies as a bug. However, combining this behavior with upward propagation is difficult.

Not propagating types to function arguments seems fine, but for variant and record
constructors this is less clear-cut.
Another option is to extend the syntactic cases where the behavior is triggered, including
"let" and "let module", but your report is about inlined functions, which could benefit
from propagation.

How much do you rely on that?
Another option, if we add "let" to the matched expression,
would be to "let-expand" your function:
  f (let g ?x ?y () = ... in g)
this way it would match the pattern, and the let is eliminated by compilation anyway.
But this workaround does not work currently.
frisch (developer)
2012-09-04 19:36

Jacques: what do you call "upward" propagation? Propagating the expected types *down* the AST?

Wouldn't it be possible to trigger the erasure of an optional argument "on the fly" when reaching a lambda node, if the expected type asks for a function type without this optional argument?

That said, I'm not a big fan of the automatic erasure of optional arguments (it looks rather fragile, and not so useful).
Martin Jambon (reporter)
2012-09-04 21:00

This problem occurs in two spots in a ~100K-line code base and I don't see much more need for it in the future.

The macro we're using is FILTER provided by mikmatch_pcre:

# let f = FILTER int eos;;
val f : ?share:bool -> ?pos:int -> string -> bool = <fun>

# List.filter (FILTER int eos) [ "-123"; "a"; "0"; "-1.2" ];;
- : string list = ["-123"; "0"]
shinwell (developer)
2017-03-07 14:40

I think the lack of activity (more than four years) on this PR suggests that there isn't a problem in this area at present.

- Issue History
Date Modified Username Field Change
2012-08-31 22:25 Martin Jambon New Issue
2012-09-04 06:12 garrigue Note Added: 0008016
2012-09-04 06:12 garrigue Assigned To => garrigue
2012-09-04 06:12 garrigue Status new => feedback
2012-09-04 19:36 frisch Note Added: 0008021
2012-09-04 21:00 Martin Jambon Note Added: 0008022
2012-09-04 21:00 Martin Jambon Status feedback => assigned
2012-09-06 16:43 doligez Target Version => 4.00.1+dev
2012-09-27 14:38 doligez Target Version 4.00.1+dev => later
2014-03-26 01:25 garrigue Relationship added related to 0006352
2017-02-23 16:45 doligez Category OCaml typing => typing
2017-03-07 14:40 shinwell Note Added: 0017596
2017-03-07 14:40 shinwell Status assigned => closed
2017-03-07 14:40 shinwell Resolution open => no change required

Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker