Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with automatic type casting of anonymous object fields #21

Closed
maxless opened this issue Feb 12, 2014 · 11 comments
Closed

Problem with automatic type casting of anonymous object fields #21

maxless opened this issue Feb 12, 2014 · 11 comments

Comments

@maxless
Copy link

maxless commented Feb 12, 2014

When I define an anonymous object with an array field and then mistakenly cast it later as a list, I receive a "null" pointer in new variable without any errors.

class Test
{
  public function new()
    {}


  public static function main()
    {
      var arr = [ 1, 2, 3 ]; // array
      var a: Dynamic = { test: 1, l: arr };
      var l: List<Dynamic> = a.l; // bug: casting as list
      trace(l);
    }
}

This code produces this result in neko:

Test.hx:12: [1,2,3]

and in hxcpp:

Test.hx:12: null

I understand that this is my mistake - casting an array as a list. But I didn't receive any meaningful errors during runtime even in debug mode and just making it null feels wrong. I'm not sure if you can do anything with that but that is pretty confusing for someone who didn't stumble on this before. Maybe there is a way to make that cast show some "type casting wrong" error?

@Simn
Copy link
Member

Simn commented Feb 12, 2014

This is expected. a is typed as Dynamic, so the compiler cannot tell what a.l is in the general case and admits the assignment. You can get rid of the Dynamic type hint to get an error from this.

@Simn Simn closed this as completed Feb 12, 2014
@maxless
Copy link
Author

maxless commented Feb 12, 2014

That was just for the example. In the actual application there is a socket connection and data serialization/deserialization between these two lines so it's not that easy. In any case why can't the runtime code throw exception or say something in the console, at least in debug mode?

@delahee
Copy link
Contributor

delahee commented Feb 12, 2014

Dynamic access is basically a way to say "I know what I do" and the
compiler will trust you.
Rephrased it just mean every time you write Dynamic it produces a tiny
Nyarlatotep invocation and that she will always find you.

Serialisation require you to retype things explicitly if you want to keep
from the eater of the worlds :)

Good luck ghfag'n
Le 12 févr. 2014 17:10, "maxless" notifications@github.com a écrit :

That was just for the example. In the actual application there is a socket
connection and data serialization/deserialization between these two lines
so it's not that easy. In any case why can't the runtime code throw
exception or say something in the console, at least in debug mode?


Reply to this email directly or view it on GitHubhttps://github.com//issues/21#issuecomment-34883920
.

@Simn
Copy link
Member

Simn commented Feb 12, 2014

Re-reading the issue, I agree it looks quite strange that you end up with a silent null value there. I'm reopening the issue for discussion.

@Simn Simn reopened this Feb 12, 2014
@delahee
Copy link
Contributor

delahee commented Feb 12, 2014

Well in cpp type casting are done in many ways and none throws an error.

In this case it looks like dynamic cast was used and returned null because
of incompatible types Static cast would have produced a badly formed
pointer along with reinterpret cast.

So maybe if haxe build a type check with a dynamic cast and ptr comparison
you can implement a sort of exception throwing cast.

Gl.
Le 12 févr. 2014 18:19, "Simon Krajewski" notifications@github.com a
écrit :

Re-reading the issue, I agree it looks quite strange that you end up with
a silent null value there. I'm reopening the issue for discussion.


Reply to this email directly or view it on GitHubhttps://github.com//issues/21#issuecomment-34892122
.

@maxless
Copy link
Author

maxless commented Feb 13, 2014

Nope, retyping won't help:

  var arr = [ 1, 2, 3 ];
  var a = { test: 1, l: arr };
  var s = haxe.Serializer.run(a); // serialize and send over network
  var b: { test: Int, l: List<Dynamic> } = haxe.Unserializer.run(s); //

receive in socket, deserialize and retype
var l: List = b.l;
trace(l); // still says null

2014-02-12 delahee notifications@github.com:

Dynamic access is basically a way to say "I know what I do" and the
compiler will trust you.
Rephrased it just mean every time you write Dynamic it produces a tiny
Nyarlatotep invocation and that she will always find you.

Serialisation require you to retype things explicitly if you want to keep
from the eater of the worlds :)

Good luck ghfag'n
Le 12 févr. 2014 17:10, "maxless" notifications@github.com a écrit :

That was just for the example. In the actual application there is a
socket
connection and data serialization/deserialization between these two
lines
so it's not that easy. In any case why can't the runtime code throw
exception or say something in the console, at least in debug mode?

Reply to this email directly or view it on GitHub<
https://github.com/HaxeFoundation/hxcpp/issues/21#issuecomment-34883920>
.

Reply to this email directly or view it on GitHubhttps://github.com//issues/21#issuecomment-34891883
.

@ncannasse
Copy link
Member

I think that when casting from Dynamic to a known class, we should perform a strict check: if the cast is not allowed it should raise an exception. This is similar to what Flash does, and prevents error propagation too deep in the program
@hughsando what do you think about it?

@Simn
Copy link
Member

Simn commented Feb 13, 2014

I agree, silently introducing a null value there is going to cause errors later anyway, so it's better to error right there.

@hughsando
Copy link
Member

I don't think there will be a problem with performance or anything -
although I use I null check for Std.is I think, so might take some work to
separate code that looks for the null explicitly.
Hugh

On Thu, Feb 13, 2014 at 7:45 PM, Simon Krajewski
notifications@github.comwrote:

I agree, silently introducing a null value there is going to cause errors
later anyway, so it's better to error right there.

Reply to this email directly or view it on GitHubhttps://github.com//issues/21#issuecomment-34971002
.

@hughsando
Copy link
Member

Hi guys,
Looking at this one again...
The neko result is of course quite wrong as well - trying "l.clear()" will not work.
Hxcpp now throws an error on invalid cast - like flash. Not sure if anyone is relying on the null behaviour - will soon find out I guess.

@ncannasse
Copy link
Member

@hughsando while you're at it, please look that Std.is/Std.instance are correctly optimized on hxcpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants