Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Compiler crashes when setter/getter is called #2

Open
keigoi opened this Issue · 4 comments

2 participants

@keigoi

The following code crashes the ocamljs compiler:

let f o = o#_get_x 1

it says:

Fatal error: exception Failure("bad method call")

while the following equivalent code compiles without crash:

let f o = let g = o#_get_x in g 1

It seems that the getter must not be applied directly to any argument, or ocamljs will die.
Although it is not fatal since there's workaround, it might be better if a more informative message is provided.

Similarly, the following code, which misses the setter's argument, will crash:

let f o = o#_set_x

The error message is the same:
Fatal error: exception Failure("bad method call")

@jaked
Owner

Thank you for the bug report.

I think both these cases could be fixed: the first by applying the gotten value to any extra arguments, the second by generating a function for the partial application of the setter.

However, there is a larger problem here, which is that over/under application of Javascript methods does not work, since we don't know their arity (and in fact they may behave differently according to the arity of their arguments). This can't be caught in the type system.

I am somewhat reluctant to fix the getter/setter special cases (where we happen to know the arity), since it can't be fixed in general.

I think your original example had to do with a missed semicolon:

let f o = o#_set_x 1 o#_set_y 1

It would of course be nice to catch this kind of problem (accidental overapplication). I suggest that functions on native Javascript objects should always have their argument type-annotated to gain a little safety.

The only good alternative I can think of is to abandon normal OCaml method call syntax and use a special syntax for Javascript calls (like js_of_ocaml does). But I would like to be convinced that it is a very serious problem before taking that path.

@jaked
Owner

Oh, also, it is difficult to give a good error message here because we are working with the lambda code, which no longer contains source locations. But it could probably be improved a little ("bad setter" / "bad getter" instead of "bad method call").

@keigoi

Thank you for your effort and immediate replies. Now I (partially) understood the problem.

I thought that overapplication to a setter should be treated as a type error. But it is impossible since it is detected in the translation phase (from lambda to js), not in the type-checking phase. Similar discussion applies to getters. correct?

(As I mentioned) I consider that this problem is not fatal. Improving the error message and explaining it in the FAQ is enough.

By the way, I'm curious about another workaround for getters, which treats

o#_get_x y z
as
let f=o#_get_x in f y z
(I do not suggest this as a solution, but just for curiosity!)

@jaked
Owner

Yes, overapplication of a setter should be a type error, but we must know the type of the setter. If you write

class type foo =
object
    method _set_x : int -> unit
end

let f (o : foo) = o#_set_x 1 2

then you get a type error. But if you leave off the annotation the compiler just propagates the constraint that _set_x has two argument to o. Now, it might be possible in ocamljs to add a type constraint 'a -> unit for all setters, but it seems like a hack, and would only work for setters. I think it is better to use annotations when working with native objects. (Actually, I find that it is very often necessary to use annotations whenever you use the object system.)

Your workaround for getters is what I meant by "applying the gotten value to any extra arguments". I think it would work fine, but since it can't work for other methods (because we don't know the arity) I think it might not be a good idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.