Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0007531OCamlmiddle end (typedtree to clambda)public2017-05-08 11:442017-05-15 12:48
Assigned Toshinwell 
PlatformOSOS Version
Product Version4.04.0 
Target VersionFixed in Version 
Summary0007531: Delayed effects in partially applied functions
DescriptionThe native code compiler erroneously delays the effect of an operator until (if ever) it is fully applied.

The following program outputs a newline when compiled with the bytecode compiler but not with the native code compiler:

    (let _i = print_newline ()
     in fun q -> fun i -> "") ()

I believe the issue is described by the following comment on line 828 of asmcomp/

(* We convert [f a] to [let a' = a in fun b c -> f a' b c]
       when fun_arity > nargs *)

which instead should use an approach along the lines of:

(* We convert [f a] to [let f’ = f in
                        let a’ = a in fun b c -> f’ a’ b c]
       when fun_arity > nargs *)

The above example illustrates the situation when the effect is delayed indefinitely. For an example, where the effect is delayed until the time of full application, consider:

    let k =
      (let _i = print_int 1
       in fun q -> fun i -> "") ()
    in k (print_int 0)

which prints 10 when compiled with the bytecode backend and 01 with the native code backend.

The behaviour is the same for version 4.02.3.
Steps To Reproduce$ ocamlc -o func.byte
$ ./func.byte

$ ocamlopt -o func.native
$ ./func.native
TagsNo tags attached.
Attached Files

- Relationships
related to 0007533resolvedshinwell Wrong code generation of e / e' and e mod e' with effectful e 

-  Notes
shinwell (developer)
2017-05-08 12:12

Sigh, unfortunately the other fixes I'd made about evaluation order haven't fixed this. Thanks for the report. I will make a patch.
shinwell (developer)
2017-05-08 13:16

Superceded by [^]
stedolan (developer)
2017-05-15 10:50

It turns out that the same issue crops up with default arguments, although this version can occur with bytecode as well as native code:

# let f ?(x = print_endline "hello") () = fun _ -> 1;;
val f : ?x:unit -> unit -> 'a -> int = <fun>
# f ();;
- : '_a -> int = <fun>
# f () ();;
- : int = 1
garrigue (manager)
2017-05-15 11:43

With defaults arguments, this is part of the specification (not sure where it is written).
I.e. the evaluation order of default arguments is left unspecified, and can be delayed until after the last functional abstraction.
I.e. side-effects in defaults are only guaranteed to occur before other side effects (in the body of the function).
This is necessary to avoid a code blow-up in native code generation.
This said, it might be sufficient to delay them until after the first non-labeled argument, which would be more intuitive in your example.
garrigue (manager)
2017-05-15 11:54

About optional arguments: the problem is described in my paper
"Labeled and optional arguments for Objective Caml" of 2001.
See the explanation at the end of section 6.
However, it seems to imply that we should not delay longer than the first non-labeled argument.
I wonder why this is not implemented that way.
garrigue (manager)
2017-05-15 12:48

Create a pull request which fixes the problem with default arguments.
Need to add some tests... [^]

- Issue History
Date Modified Username Field Change
2017-05-08 11:44 jmi New Issue
2017-05-08 12:12 shinwell Note Added: 0017778
2017-05-08 12:12 shinwell Assigned To => shinwell
2017-05-08 12:12 shinwell Status new => assigned
2017-05-08 13:16 shinwell Note Added: 0017779
2017-05-08 13:17 shinwell Status assigned => resolved
2017-05-08 13:17 shinwell Resolution open => duplicate
2017-05-12 22:46 gasche Relationship added related to 0007533
2017-05-15 10:50 stedolan Note Added: 0017797
2017-05-15 11:43 garrigue Note Added: 0017798
2017-05-15 11:54 garrigue Note Added: 0017799
2017-05-15 12:48 garrigue Note Added: 0017800

Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker