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

go/types, types2: self-contradictory error message when separating the definition and implementation of an interface with anonymous structs in a method signature #54258

Closed
guamoko995 opened this issue Aug 4, 2022 · 12 comments
Assignees
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@guamoko995
Copy link

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

$ go version
go version go1.19 linux/amd64

Does this issue reproduce with the latest release?

yes

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/guamoko95/.cache/go-build"
GOENV="/home/guamoko95/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/guamoko95/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/guamoko95/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.19"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/guamoko95/go/src/play/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build3021280297=/tmp/go-build -gno-record-gcc-switches"

What did you do?

package main

import "play/implementation"

// interface declaration with anonymous non-empty structure in signature

type AnonNonEmptyStructGeter interface {
	AnonNonEmptyStructGet() struct{ string }
}

func main() {
	var w AnonNonEmptyStructGeter
	w = implementation.ImpAnonNonEmptyStructGeter{}
}

play/implementation:

package implementation

// interface implementation with anonymous non-empty struct in signature
type ImpAnonNonEmptyStructGeter struct{}

func (ImpAnonNonEmptyStructGeter) AnonNonEmptyStructGet() struct{ string } {
	return struct{ string }{""}
}

What did you expect to see?

successful compilation or compilation error message indicating a problem. For example: "anonymous types in different packages"

What did you see instead?

self-contradictory error message:

# command-line-arguments
./main.go:13:6: cannot use implementation.WithMetodWithAnonStruct{} (value of type implementation.WithMetodWithAnonStruct) 
as type WithAnonNonEmptyStructer in assignment:
        implementation.WithMetodWithAnonStruct does not implement WithAnonNonEmptyStructer (wrong type for WithAnonStruct method)
                have WithAnonStruct() struct{string}
                want WithAnonStruct() struct{string}
@guamoko995 guamoko995 changed the title affected/package: go/build go/build: self-contradictory error message Aug 4, 2022
@guamoko995 guamoko995 changed the title go/build: self-contradictory error message go/build: self-contradictory error message when separating the definition and implementation of an interface with anonymous types in a method signature. Aug 4, 2022
@guamoko995 guamoko995 changed the title go/build: self-contradictory error message when separating the definition and implementation of an interface with anonymous types in a method signature. go/build: self-contradictory error message when separating the definition and implementation of an interface with anonymous structs in a method signature. Aug 4, 2022
@dmitshur dmitshur added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. compiler/runtime Issues related to the Go compiler and/or runtime. labels Aug 4, 2022
@dmitshur dmitshur added this to the Backlog milestone Aug 4, 2022
@dmitshur dmitshur changed the title go/build: self-contradictory error message when separating the definition and implementation of an interface with anonymous structs in a method signature. cmd/compile: self-contradictory error message when separating the definition and implementation of an interface with anonymous structs in a method signature Aug 4, 2022
@dmitshur
Copy link
Contributor

dmitshur commented Aug 4, 2022

CC @golang/compiler.

@mdempsky
Copy link
Member

mdempsky commented Aug 4, 2022

struct{string} denotes different types when it appears in different packages. So failing to type check is the correct behavior here.

Agreed the error message is unfortunate for not being able to disambiguate that though.

/cc @griesemer @findleyr

@mdempsky mdempsky changed the title cmd/compile: self-contradictory error message when separating the definition and implementation of an interface with anonymous structs in a method signature go/types, types2: self-contradictory error message when separating the definition and implementation of an interface with anonymous structs in a method signature Aug 4, 2022
@findleyr
Copy link
Contributor

findleyr commented Aug 4, 2022

Ack, this is unfortunate and confusing. It would be good to clarify that the identity of the string field does not match here.

I am not sure how high a priority this is, but we do want to continue to improve error messages in the new type checker. (I have not yet checked whether the old type checker produced a better message here).

@mknyszek
Copy link
Contributor

@findleyr As part of triage assigning to you for now, but please feel free to unassign! Noted the low-ish priority.

@mknyszek mknyszek assigned findleyr and dr2chase and unassigned findleyr Aug 10, 2022
@mknyszek
Copy link
Contributor

Reassigning to @dr2chase who volunteered to take a quick look.

@dr2chase
Copy link
Contributor

The new type checker is annoying in its parsimony; structs, which can have packages as part of their identity, don't know their own packages. The old type checker was similarly confusing.

I have a maybe fix, subject to passing tests. I'm not proud of it....

@mdempsky
Copy link
Member

mdempsky commented Aug 10, 2022

structs, which can have packages as part of their identity, don't know their own packages

Named structs you can find their package with Named.Obj().Pkg().

Anonymous, non-empty structs you can find their package with Struct.Field(0).Pkg(). (A struct definition can't span multiple packages, so all of its fields must exist in the same package.)

The anonymous, empty struct is identical in all packages.

@findleyr
Copy link
Contributor

The new type checker is annoying in its parsimony; structs, which can have packages as part of their identity, don't know their own packages.

Struct fields are objects, which have access to their package.

@findleyr
Copy link
Contributor

To expand: this rule is implemented in types.identical, the call to sameId for struct fields.

To implement this, we'd probably need to pass a reason *string argument into types.identical, similarly to what we do for other predicates. (aside, per the discovery in #54172, we should avoid building this reason if it won't be used).

@griesemer griesemer self-assigned this Aug 10, 2022
@gopherbot
Copy link

Change https://go.dev/cl/422914 mentions this issue: cmd/compile: package-annotate structs when error would be ambiguous

@griesemer
Copy link
Contributor

Simplified reducer, for use as test case, and for the benefit of other readers:

// file a.go
package a

type S struct{}

func (S) M() (_ struct{ f string }) {
	return
}
package b

import "./a"

type I interface {
	M() (_ struct{ f string })
}

var _ I = a.S{}

Similar to the original, the error message is:

b.go:9:11: cannot use a.S{} (value of type a.S) as type I in variable declaration:
	a.S does not implement I (wrong type for M method)
		have M() (_ struct{f string})
		want M() (_ struct{f string})

The code compiles if the field f is exported (capitalized) in both files. The "field name" for an embedded type (string in the original code) is the type name (string), which happens to be lower-case and thus not exported. Not exported names from different packages are always different.

As stated before, the compiler is correct to reject this code.

@dmitshur dmitshur modified the milestones: Backlog, Go1.20 Nov 19, 2022
@dmitshur dmitshur added NeedsFix The path to resolution is known, but the work has not been done. and removed NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Nov 19, 2022
@gopherbot
Copy link

Change https://go.dev/cl/452455 mentions this issue: go/types, types2: better variable names, cleanups in test

gopherbot pushed a commit that referenced this issue Nov 21, 2022
For #54258.

Change-Id: Ib0d326af2719bca1579f84c125f6573f87dce982
Reviewed-on: https://go-review.googlesource.com/c/go/+/452455
Run-TryBot: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
felixge pushed a commit to felixge/go that referenced this issue Nov 21, 2022
For golang#54258.

Change-Id: Ib0d326af2719bca1579f84c125f6573f87dce982
Reviewed-on: https://go-review.googlesource.com/c/go/+/452455
Run-TryBot: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
@golang golang locked and limited conversation to collaborators Nov 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

8 participants