Version française
Home     About     Download     Resources     Contact us    
Browse thread
weird behavior with built-in ignore function (a bug?)
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Julien Moutinho <julien.moutinho@g...>
Subject: Re: [Caml-list] weird behavior with built-in ignore function (a bug?)
On Fri, Nov 23, 2007 at 11:09:44AM -0500, Peng Zang wrote:
> I have run into what appears to be very odd behavior with the built-in
> function "ignore".  I will demonstrate below.  It's a little
> complicated, but it's the smallest testcase I could make it:
> 
> # type 'a fruit = 'a
> and 'b veggie = 'b
> and ('a,'b) kitchen = { source : <make : 'a fruit>;
>                         sink : <trans : 'a fruit -> 'b veggie>; }
> ;;
> 
> # let bar sink x = sink#trans x;;
> val bar : < trans : 'a -> 'b; .. > -> 'a -> 'b = <fun>
> 
> # let foo src snk =
>     let m = { source = src; sink = snk } in
>       ignore (bar m.sink m.source#make);
>       ignore (bar m.sink m.source#make);
>       ()
> ;;
> val foo : < make : 'a fruit > -> < trans : 'a fruit -> '_b veggie > -> unit = 
> <fun>
> 
> 
> Basically, we have two objects.  One is producing fruits (source) and
> the other is transforming them into vegetables (sink).  Note the
> inferred typesig of foo, it thinks the trans method returntype is '_b
> veggie.  This seems strange.  I think it should return a fully
> polymorphic 'b veggie.
[..]

AFAICS it has been fixed in the release310 branch:
  http://caml.inria.fr/mantis/view.php?id=4350

% git checkout release310
Switched to branch "release310"
% make ocamlc
[...]
% ./ocamlc -i peng__071123.ml
type 'a fruit = 'a
and 'a veggie = 'a
and ('a, 'b) kitchen = {
  source : < make : 'a fruit >;
  sink : < trans : 'a fruit -> 'b veggie >;
}
val bar : < trans : 'a -> 'b; .. > -> 'a -> 'b
val foo : < make : 'a fruit > -> < trans : 'a fruit -> 'b veggie > -> unit

% git-log --grep='PR#4350'
commit 4240263b7cbe15e87cc24e797aac6917eacb9f71
Author: garrigue <garrigue>
Date:   Mon Oct 29 04:40:34 2007 +0000

    PR#4350
% git-revert 4240263b
% make ocamlc
% ./ocamlc -i peng__071123.ml
type 'a fruit = 'a
and 'a veggie = 'a
and ('a, 'b) kitchen = {
  source : < make : 'a fruit >;
  sink : < trans : 'a fruit -> 'b veggie >;
}
val bar : < trans : 'a -> 'b; .. > -> 'a -> 'b
val foo : < make : 'a fruit > -> < trans : 'a fruit -> '_b veggie > -> unit

% git-reset --hard 'HEAD^'

> To verify.  I now re-define foo without the use of ignore:
> 
> # let foo src snk =
>     let m = { source = src; sink = snk } in
>     let _ = bar m.sink m.source#make in
>     let _ = bar m.sink m.source#make in
>       ();;
> val foo : < make : 'a fruit > -> < trans : 'a fruit -> 'b veggie > -> unit = 
> <fun>
> 
> This time the return type for trans is fully polymorphic!  Using
> ignore as in the first case broke something.
> 
> For a strange turn, I make my own ignore function and redefine foo
> with that:
> 
> # let myignore x = ();;
> val myignore : 'a -> unit = <fun>
> # let foo src snk =
>   let m = { source = src; sink = snk } in
>     myignore (bar m.sink m.source#make);
>     myignore (bar m.sink m.source#make);
>     ()
> ;;
> val foo : < make : 'a fruit > -> < trans : 'a fruit -> 'b veggie > -> unit = 
> <fun>
> 
> This also yields returns a fully polymorphic veggie!  So it's
> something unique to the build-in ignore function?
Perhaps the fact that Pervasives.ignore is defined like that:

  external ignore : 'a -> unit = "%ignore"

BTW be aware that:
% ocaml
        Objective Caml version 3.10.1+dev2 (2007-11-20)

# ignore == ignore;;
- : bool = false
# let ignore _ = ();;
val ignore : 'a -> unit = <fun>
# ignore == ignore;;
- : bool = true

> So now my puzzling question: what is going on?  What is wrong with the
> build-in ignore function that would make it mess up the return type of
> the trans method?  Is this a bug?
> 
> Thanks,
> 
> Peng
> 
> PS. I'm using OCaml 3.09.3, haven't tried with 3.10

HTH,
  Julien.