Skip to content

Struct field assigned nil != nil #639

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
theclapp opened this issue May 3, 2017 · 5 comments
Open

Struct field assigned nil != nil #639

theclapp opened this issue May 3, 2017 · 5 comments
Labels
bug NeedsFix NeedsHelp Community contributions are welcome for this feature!

Comments

@theclapp
Copy link

theclapp commented May 3, 2017

Why doesn't t1.foo == nil, after I just assigned it nil? Why doesn't it even == itself?

type foo struct {
	*js.Object
	bar bool `js:"bar"`
}
type t struct {
	*js.Object
	*foo `js:"foo"`
}

t1 := t{Object: js.Global.Get("Object").New()}
t1.foo = nil

// => "t1.foo != nil"
if t1.foo == nil {
	fmt.Println("t1.foo == nil")
} else {
	fmt.Println("t1.foo != nil")
}
fmt.Printf("t1.foo is %v\n", t1.foo) // => "t1.foo is null"

// => "t1.foo != itself"
if t1.foo == t1.foo {
	fmt.Println("t1.foo == itself")
} else {
	fmt.Println("t1.foo != itself")
}

Playground link

Am I doing something wrong? Is there a better way to deal with this?

@dmitshur
Copy link
Member

dmitshur commented May 3, 2017

This definitely seems very messed up.

Here's my attempt at doing better with dealing with it, but it's still not great.

https://gopherjs.github.io/playground/#/k4XCYLcu0T

I made foo not embedded in t, compared foo.Objects instead of foos, and used pointer to &t.

This is why we have a proposal like #633 to clean up how these structs behave. /cc @myitcv

@theclapp
Copy link
Author

theclapp commented May 3, 2017

Thanks. Comparing foo.Objects (e.g. t1.foo.Object) instead of foos was key. I hadn't thought of that.

@myitcv
Copy link
Member

myitcv commented May 3, 2017

Thanks @theclapp

Can't look in detail right now, so this is a bit of a drive-by comment.

Firstly I agree @shurcooL your correction to t1 := &t{... is important here. This catch adds weight to @flimzy's comment from last week

Looking at the transpiled code:

var t1 *t
_ = t1 == t1

results in:

var $ptr, t1;
t1 = ptrType.nil;
$unused(t1 === t1);

Whereas:

var t1 *t
_ = t1.foo == t1.foo

results in:

var $ptr, t1;
t1 = ptrType.nil;
$unused($internalize(t1.Object.foo, ptrType$1) === $internalize(t1.Object.foo, ptrType$1));

Referring to what I think is the relevant code the case uncovered by @theclapp arises because selector expressions that result in a field value (t1.foo is such an expression) unconditionally $internalize.

So immediately there is a discrepancy in the transpiled code between t1 == t1 and t1.foo == t1.foo, despite them both expressions involved being pointers to *js.Object-struct type values.

At which point I'd be tempted to put this in the bucket of #617. But given botht and foo are *js.Object-special types it inevitably spills over into #633 (as you say @shurcooL).

Either way, we need to work out what we should be doing here (my knee-jerk reaction is that we shouldn't be $internalize-ing any value of type pointer to *js.Object-special struct value, but that's with very little dedicated thought!)

Just to be clear, the comparison is irrelevant here; it boils down to the transpilation of the operands of the binary expression that matters... and this is what's going wrong

@theclapp
Copy link
Author

theclapp commented Apr 9, 2021

As near as I can tell this is still a problem, even if you fix the part where I used t{} instead of &t{}.

Playground link

@flimzy
Copy link
Member

flimzy commented Apr 9, 2021

Based on superficial observation only, this may be related to #843

@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