caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Magic with fun (type t) ... ?
@ 2011-01-26 22:17 Jim Pryor
  2011-01-26 22:33 ` David Allsopp
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Jim Pryor @ 2011-01-26 22:17 UTC (permalink / raw)
  To: caml-list

I expect this is bad coding style, and should not be relied on. However,
I was surprised at the behavior, and wondered whether it was intended:

# let f = fun (type t) x ->
    let module M = struct exception E of t end in
    M.E x;;
val f : 'a -> exn = <fun>

f is polymorphic, as we expect:

# f 1;;
- : exn = E 1
# f "s";;
- : exn = E "s"

But now notice:

# f ();;
- : exn = E 0
# f None;;
- : exn = E 0

It appears that non-heap values are always getting magicked into ints.

Has this been noted before?

-- 
Jim Pryor
profjimm@jimpryor.net

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [Caml-list] Magic with fun (type t) ... ?
  2011-01-26 22:17 [Caml-list] Magic with fun (type t) ... ? Jim Pryor
@ 2011-01-26 22:33 ` David Allsopp
  2011-01-27  6:13   ` Alain Frisch
  2011-01-26 22:34 ` Jim Pryor
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: David Allsopp @ 2011-01-26 22:33 UTC (permalink / raw)
  To: 'Jim Pryor', 'caml-list@inria.fr'

Jim Pryor wrote:
> I expect this is bad coding style, and should not be relied on. However,
> I was surprised at the behavior, and wondered whether it was intended:
> 
> # let f = fun (type t) x ->
>     let module M = struct exception E of t end in
>     M.E x;;
> val f : 'a -> exn = <fun>
> 
> f is polymorphic, as we expect:
> 
> # f 1;;
> - : exn = E 1
> # f "s";;
> - : exn = E "s"
> 
> But now notice:
> 
> # f ();;
> - : exn = E 0
> # f None;;
> - : exn = E 0
> 
> It appears that non-heap values are always getting magicked into ints.

I think there are other situations (I can't remember how you can force them) where the toploop displays the "wrong" things. As I understand it, the compiler/interpreter really has to jump through hoops sometimes to display the correct version of a value because the value representation throws away so much (virtually) of the typing information.

> Has this been noted before?

However, this is weird since () and the constructor None are not equal in OCaml-land (they happen to have equivalent representation, but that's not the same thing):

# f () = f None;;
- : bool = true


David


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Magic with fun (type t) ... ?
  2011-01-26 22:17 [Caml-list] Magic with fun (type t) ... ? Jim Pryor
  2011-01-26 22:33 ` David Allsopp
@ 2011-01-26 22:34 ` Jim Pryor
  2011-01-26 23:07 ` Guillaume Yziquel
  2011-01-26 23:11 ` Gabriel Scherer
  3 siblings, 0 replies; 7+ messages in thread
From: Jim Pryor @ 2011-01-26 22:34 UTC (permalink / raw)
  To: caml-list

On Wed, Jan 26, 2011 at 05:17:56PM -0500, Jim Pryor wrote:
> I expect this is bad coding style, and should not be relied on. However,
> I was surprised at the behavior, and wondered whether it was intended:
> 
> # let f = fun (type t) x ->
>     let module M = struct exception E of t end in
>     M.E x;;
> val f : 'a -> exn = <fun>
> 
> f is polymorphic, as we expect:
> 
> # f 1;;
> - : exn = E 1
> # f "s";;
> - : exn = E "s"
> 
> But now notice:
> 
> # f ();;
> - : exn = E 0
> # f None;;
> - : exn = E 0
> 
> It appears that non-heap values are always getting magicked into ints.
> 
> Has this been noted before?

I expect it's probably harmless, because what could you do with the
exception value in question? Since it's leaked outside the scope of its
type declaration, I can't see any (unmagicky) way to
deconstruct it. But as I said, this behavior struck me as odd. I
would more have expected an error.

-- 
Jim Pryor
profjim@jimpryor.net

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Magic with fun (type t) ... ?
  2011-01-26 22:17 [Caml-list] Magic with fun (type t) ... ? Jim Pryor
  2011-01-26 22:33 ` David Allsopp
  2011-01-26 22:34 ` Jim Pryor
@ 2011-01-26 23:07 ` Guillaume Yziquel
  2011-01-26 23:11 ` Gabriel Scherer
  3 siblings, 0 replies; 7+ messages in thread
From: Guillaume Yziquel @ 2011-01-26 23:07 UTC (permalink / raw)
  To: caml-list

Le Wednesday 26 Jan 2011 à 17:17:56 (-0500), Jim Pryor a écrit :
> 
> It appears that non-heap values are always getting magicked into ints.
> 
> Has this been noted before?

I noted this. It seems to me that the toplevel's behaviour has changed
in the 3.12 release. It doesn't seem to rely on available type
information to display the exception, but rather seems to inspect the
low-level layout of the exception's content. None and 0 are the same.
Strings are not.
 
I may be mistaken, but it seems to that I was raising exceptions in the
toplevel with arguments that were custom blocks. This made the toplevel
segfault when trying to read the custom block.
 
I feel that this is a regression from previous OCaml toplevel behaviour,
but I'm not so sure.

-- 
     Guillaume Yziquel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Magic with fun (type t) ... ?
  2011-01-26 22:17 [Caml-list] Magic with fun (type t) ... ? Jim Pryor
                   ` (2 preceding siblings ...)
  2011-01-26 23:07 ` Guillaume Yziquel
@ 2011-01-26 23:11 ` Gabriel Scherer
  3 siblings, 0 replies; 7+ messages in thread
From: Gabriel Scherer @ 2011-01-26 23:11 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 1873 bytes --]

Local modules are usually "safe" in the sense that the type system checks
that the local types do not escape the whole expression.

  # let test =
      let module Local = struct type t = Foo end
      in Local.Foo;;
  Error: This `let module' expression has type Local.t
  In this type, the locally bound module name Local escapes its scope

However, exceptions do not create a local type, they instead augment the
global open-ended "exn" type, so the type-checker won't detect the leak.

Finally, you don't want to disallow local exception declarations, as they're
very useful in various situations -- simply moving an existing module to a
local scope.
The use of the new (type t) construct to declare local polymorphic
exceptions is also useful in some cases. See for example:
http://ocaml.janestreet.com/?q=node/18#comment-190


(I agree that the type regression when escaping is quite weird and should be
avoided if possible.)


On Wed, Jan 26, 2011 at 11:17 PM, Jim Pryor
<lists+caml@jimpryor.net<lists%2Bcaml@jimpryor.net>
> wrote:

> I expect this is bad coding style, and should not be relied on. However,
> I was surprised at the behavior, and wondered whether it was intended:
>
> # let f = fun (type t) x ->
>    let module M = struct exception E of t end in
>    M.E x;;
> val f : 'a -> exn = <fun>
>
> f is polymorphic, as we expect:
>
> # f 1;;
> - : exn = E 1
> # f "s";;
> - : exn = E "s"
>
> But now notice:
>
> # f ();;
> - : exn = E 0
> # f None;;
> - : exn = E 0
>
> It appears that non-heap values are always getting magicked into ints.
>
> Has this been noted before?
>
> --
> Jim Pryor
> profjimm@jimpryor.net
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>

[-- Attachment #2: Type: text/html, Size: 2898 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Magic with fun (type t) ... ?
  2011-01-26 22:33 ` David Allsopp
@ 2011-01-27  6:13   ` Alain Frisch
  2011-01-27 23:56     ` Guillaume Yziquel
  0 siblings, 1 reply; 7+ messages in thread
From: Alain Frisch @ 2011-01-27  6:13 UTC (permalink / raw)
  To: David Allsopp; +Cc: 'Jim Pryor', 'caml-list@inria.fr'

On 1/26/2011 11:33 PM, David Allsopp wrote:
>> # f ();;
>> - : exn = E 0
>> # f None;;
>> - : exn = E 0

>
> # f () = f None;;
> - : bool = true


There are two distinct problems here, neither of which has been 
introduced in 3.12.

First, the toplevel uses types to display exception arguments only when 
it knows exactly their type. Otherwise, there is a fallback heuristic to 
look at runtime tags.

# module X : sig val x : exn end = struct exception E of int option let 
x = E None end;;
module X : sig val x : exn end
# X.x;;
- : exn = X.E 0


Second, exception values values are compared structurally; this means 
that the constructors are compared textually and when they match, the 
arguments are compared even if they don't have the same type (yes, this 
can probably yield to segfaults).

# exception E of unit;;
exception E of unit
# let e1 = E ();;
val e1 : exn = E ()
# exception E of int option;;
exception E of int option
# let e2 = E None;;
val e2 : exn = E None
# e1 = e1;;
- : bool = true


Of course, pattern matching on exceptions uses the true equality between 
constructors (with a generative semantics). This is only a problem with 
the generic comparison functions.


Cf:
http://caml.inria.fr/mantis/view.php?id=1248
http://caml.inria.fr/mantis/view.php?id=4531
http://caml.inria.fr/mantis/view.php?id=4765
http://caml.inria.fr/mantis/view.php?id=5087



Alain

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Magic with fun (type t) ... ?
  2011-01-27  6:13   ` Alain Frisch
@ 2011-01-27 23:56     ` Guillaume Yziquel
  0 siblings, 0 replies; 7+ messages in thread
From: Guillaume Yziquel @ 2011-01-27 23:56 UTC (permalink / raw)
  To: Alain Frisch; +Cc: David Allsopp, Jim Pryor, caml-list

Le Thursday 27 Jan 2011 à 07:13:42 (+0100), Alain Frisch a écrit :
> 
> There are two distinct problems here, neither of which has been
> introduced in 3.12.
> 
> First, the toplevel uses types to display exception arguments only
> when it knows exactly their type. Otherwise, there is a fallback
> heuristic to look at runtime tags.

But how does the toplevel determines types? My exception type was
perfectly declared and available in the .cmi file. Yet, before 3.12 I
got the <abstr> or similar displayed in the toplevel, and in 3.12 it
started segfaulting.

I'm simply wondering whether or not the heuristic gets triggered more
easily in 3.12 than it was before. It's just a gut feeling. Nothing I
can prove.

> Second, exception values values are compared structurally; this
> means that the constructors are compared textually and when they
> match, the arguments are compared even if they don't have the same
> type (yes, this can probably yield to segfaults).

My segfault wasn't about comparing two exceptions using generic
comparison, but merely not being able to display it in 3.12's toplevel.
 
> Cf:
> http://caml.inria.fr/mantis/view.php?id=1248
> http://caml.inria.fr/mantis/view.php?id=4531
> http://caml.inria.fr/mantis/view.php?id=4765
> http://caml.inria.fr/mantis/view.php?id=5087

Thanks for the background info.

-- 
     Guillaume Yziquel


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-01-27 23:58 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-26 22:17 [Caml-list] Magic with fun (type t) ... ? Jim Pryor
2011-01-26 22:33 ` David Allsopp
2011-01-27  6:13   ` Alain Frisch
2011-01-27 23:56     ` Guillaume Yziquel
2011-01-26 22:34 ` Jim Pryor
2011-01-26 23:07 ` Guillaume Yziquel
2011-01-26 23:11 ` Gabriel Scherer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).