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

builtin: new() broken for empty struct types #23413

Closed
thwd opened this issue Jan 11, 2018 · 4 comments
Closed

builtin: new() broken for empty struct types #23413

thwd opened this issue Jan 11, 2018 · 4 comments

Comments

@thwd
Copy link

@thwd thwd commented Jan 11, 2018

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

1.9.2 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

linux/amd64

What did you do?

https://play.golang.org/p/xTqB19F6f5J

package main

import (
	"fmt"
)

type T struct{}

func main() {
	m := make(map[*T]bool)
	for i := 0; i < 32; i++ {
		m[new(T)] = false
	}
	fmt.Println(m)
}

What did you expect to see?

I expect to see a map with 32 distinct entries.

What did you see instead?

I see a map with a single entry.

Note that this behavior only occurs when T is struct{}, if you change it to e.g. bool you get 32 entries.

Also note that using a composite literal instead does not help.

I suspect this is an over-optimization issue.

@randall77
Copy link
Contributor

@randall77 randall77 commented Jan 11, 2018

This is expected. The spec says

Pointers to distinct zero-size variables may or may not be equal.

You're seeing the equal case.

@randall77 randall77 closed this Jan 11, 2018
@dsnet
Copy link
Member

@dsnet dsnet commented Jan 11, 2018

Note that this has been the behavior since Go1.1.

@dsnet
Copy link
Member

@dsnet dsnet commented Jan 11, 2018

@randall77, I don't think that is true. The section of the spec you are quoting is how comparisons are done. At least in Go1.8, pointers to zero-length values are still compared based on the pointer:

var s = struct {
	t1 T
	_  int
	t2 T
}{}

m := make(map[*T]bool)
m[&s.t1] = true
m[&s.t2] = true
fmt.Println(m) // map[0xc42000e250:true 0xc42000e258:true]

It's just that since Go1.1, the new function returned the same address for zero-length values. The allocation section does not forbid this, so it seems to be okay behavior.

@randall77
Copy link
Contributor

@randall77 randall77 commented Jan 11, 2018

@dsnet, I'm not sure what you are objecting to.

The code you posted is allowed by the spec to result in a map with only one element.

There are many ways to get a pointer to a zero-sized variable. The compiler/runtime will make some of them equal and some of them not, kind of arbitrarily.

@mikioh mikioh changed the title new() broken for empty struct types builtin: new() broken for empty struct types Jan 13, 2018
@golang golang locked and limited conversation to collaborators Jan 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants