Skip to content

Typecasting nil results in non-nil #843

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

Open
seanburke-wf opened this issue Jul 17, 2018 · 4 comments
Open

Typecasting nil results in non-nil #843

seanburke-wf opened this issue Jul 17, 2018 · 4 comments
Labels
bug NeedsFix NeedsHelp Community contributions are welcome for this feature!

Comments

@seanburke-wf
Copy link

seanburke-wf commented Jul 17, 2018

If a variable has value nil and is typecast, the result will have a non-nil value which appears to be an invalid pointer. This differs from the behavior of Go.

The following illustrate the difference in behaviors between Go and compiled gopherjs:
https://play.golang.org/p/_feur6S2EjC
https://gopherjs.github.io/playground/#/y785Hlp5q0

Additionally, the non-nil value appears to be an invalid reference:
https://play.golang.org/p/ugzWXe4x2HE
https://gopherjs.github.io/playground/#/HkVf0Bqs1m

@flimzy
Copy link
Member

flimzy commented Jul 18, 2018

Nice find. Note, however, that this is a case of type conversion, not type casting.

@theclapp
Copy link

Quick-and-possibly-dirty solution that may be a real fix, or at least may help point the way towards one:

diff --git a/compiler/prelude/types.go b/compiler/prelude/types.go
index a8c29d5..7e81b22 100644
--- a/compiler/prelude/types.go
+++ b/compiler/prelude/types.go
@@ -273,6 +273,7 @@ var $newType = function(size, kind, string, named, pkg, exported, constructor) {
       });
       typ.ptr.nil = Object.create(constructor.prototype, properties);
       typ.ptr.nil.$val = typ.ptr.nil;
+      typ.ptr.nil.isNil = true;
       /* methods for embedded fields */
       $addMethodSynthesizer(function() {
         var synthesizeMethod = function(target, m, f) {

diff --git a/compiler/prelude/prelude.go b/compiler/prelude/prelude.go
index 1eed6c4..2c754ec 100644
--- a/compiler/prelude/prelude.go
+++ b/compiler/prelude/prelude.go
@@ -317,6 +317,9 @@ var $pointerOfStructConversion = function(obj, type) {
     obj.$proxies[type.string] = proxy;
     proxy.$proxies = obj.$proxies;
   }
+  if (obj.isNil) {
+    return type.nil;
+  }
   return proxy;
 };

Test case:

var foo *FooType = nil
fmt.Println("foo is nil?", foo == nil)
var bar *BarType = (*BarType)(foo)
fmt.Println("bar is nil?", bar == nil)

foo = nil
fmt.Printf("foo is %v\n", foo)

bar = (*BarType)(foo)
fmt.Printf("bar is %v\n", bar)

=>

foo is nil? true
bar is nil? true
foo is <nil>
bar is <nil>

@seanburke-wf
Copy link
Author

Appreciate the correction on the terminology.

@regenvanwalbeek-wf
Copy link

I discovered a case very similar to the second example @seanburke-wf posted

https://play.golang.org/p/4Qn21VLSJq8
https://gopherjs.github.io/playground/#/xuA4ovI9mf

If a pointer to a struct is nil and casted to another another type declared in a type definition, the gopherjs version will panic for a nil pointer dereference.

@flimzy flimzy added bug NeedsFix NeedsHelp Community contributions are welcome for this feature! labels Apr 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug NeedsFix NeedsHelp Community contributions are welcome for this feature!
Projects
None yet
Development

No branches or pull requests

4 participants