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

cmd/compile: unexpected behavior difference between global and in-function variable definition #19482

Closed
dcarbone opened this issue Mar 9, 2017 · 11 comments

Comments

Projects
None yet
9 participants
@dcarbone
Copy link

commented Mar 9, 2017

Please answer these questions before submitting your issue. Thanks!

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

go version go1.7.5 darwin/amd64

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

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/dcarbone/code/golang"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.7.5/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.7.5/libexec/pkg/tool/darwin_amd64"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/2c/s7sg4r5s1td507l7sglm2pzw9l4z5w/T/go-build267410383=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"

What did you do?

Works:

package main

import "fmt"

type mytype struct {
	_ string
}

var foo = mytype{"foo"}

func main() {
	fmt.Printf("%#v\n", foo)
}

Fails:

package main

import "fmt"

type mytype struct {
	_ string
}

func main() {
	var foo = mytype{"foo"}
	fmt.Printf("%#v\n", foo)
}

What did you expect to see?

Either both fail or both succeed

What did you see instead?

When defining the variable in global space, the script executes. When attempting to define the variable within the main function, the script fails to compile.

Apologies if this is expected behavior, but I was unable to locate any documentation indicating as much.

@josharian josharian changed the title Unexpected behavior difference between global and in-function variable definition cmd/compile: unexpected behavior difference between global and in-function variable definition Mar 9, 2017

@josharian

This comment has been minimized.

Copy link
Contributor

commented Mar 9, 2017

Reproduced with tip. The error message is:

x.go:10: cannot refer to blank field or method

This seems odd to me too.

@josharian josharian added this to the Go1.9 milestone Mar 9, 2017

@josharian

This comment has been minimized.

Copy link
Contributor

commented Mar 9, 2017

I don't see anything in https://golang.org/ref/spec#Composite_literals that forbids this.

@josharian

This comment has been minimized.

Copy link
Contributor

commented Mar 9, 2017

@spellgen

This comment has been minimized.

Copy link

commented Mar 9, 2017

Is there any intended use of a blank identifier for the field name other than padding in structs?

@ENACaseyBoone

This comment has been minimized.

Copy link

commented Mar 9, 2017

Just to add, we found structs with underscore entries in some source code and had no idea what it was intended to do. Someone in the Gophers Slack group said that the underscore entry would make it so you were forced to use named field constructors and not lazy construction. While playing with this, @dcarbone found that the behavior changed depending on if you tried to create the var in global or in local scope

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Mar 9, 2017

Both versions compile with gccgo.

@odeke-em

This comment has been minimized.

Copy link
Member

commented Mar 9, 2017

Not necessarily related to, but it reminds me of #15481 (comment) in which
the bug report was spurious "cannot use _ as value" error and I noticed that https://play.golang.org/p/hz5ePuCDlF

package main

type m map[string]string

var _ = map[string]string{}       // ok
var _ = map[string]string{"": ""} // ok

func main() {
	var _ = map[string]string{}           // ok
	var _ = map[string]bool{}             // ok
	var _ = map[string]string{"a": "A"}   // error: cannot use _ as value
	var _ = map[string]bool{"true": true} // error: cannot use _ as value
}

had different results in the global vs function, somewhat similar to the _ check when in a function but successful compilation in the global scope.

@cespare

This comment has been minimized.

Copy link
Contributor

commented Mar 9, 2017

@griesemer

This comment has been minimized.

Copy link
Contributor

commented Mar 9, 2017

This is just a bug in the compiler.

It's clearly correct code (and gccgo and gotype accept this). May or may not be related to #15481 (see @odeke-em 's comment above).

@josharian

This comment has been minimized.

Copy link
Contributor

commented Mar 10, 2017

Unrelated to #15481, as far as I can tell.

@gopherbot

This comment has been minimized.

Copy link

commented Mar 13, 2017

CL https://golang.org/cl/38006 mentions this issue.

josharian added a commit to josharian/go that referenced this issue Mar 18, 2017

cmd/compile: allow composite literal structs with _ fields
Given code such as

type T struct {
  _ string
}

func f() {
  var x = T{"space"}
  // ...
}

the compiler rewrote the 'var x' line as

var x T
x._ = "space"

The compiler then rejected the assignment to
a blank field, thus rejecting valid code.

The only way such an assignment is legal
is to use a composite literal in which
the struct fields are provided implicitly.
When we encounter such struct fields,
mark them as allowing assignment to a blank field,
and check for the exception at the right moment.

Fixes golang#19482

Change-Id: I594476171d15e6e8ecc6a1749e3859157fe2c929

@gopherbot gopherbot closed this in c944639 Apr 7, 2017

lparth added a commit to lparth/go that referenced this issue Apr 13, 2017

cmd/compile: allow composite literal structs with _ fields
Given code such as

type T struct {
  _ string
}

func f() {
  var x = T{"space"}
  // ...
}

the compiler rewrote the 'var x' line as

var x T
x._ = "space"

The compiler then rejected the assignment to
a blank field, thus rejecting valid code.

It also failed to catch a number of invalid assignments.
And there were insufficient checks for validity
when emitting static data, leading to ICEs.

To fix, check earlier for explicit blanks field names,
explicitly handle legit blanks in sinit,
and don't try to emit static data for nodes
for which typechecking has failed.

Fixes golang#19482

Change-Id: I594476171d15e6e8ecc6a1749e3859157fe2c929
Reviewed-on: https://go-review.googlesource.com/38006
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

@golang golang locked and limited conversation to collaborators Apr 7, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.