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: comparison of Defined (Named) types fails #35265

Closed
guzenok opened this issue Oct 31, 2019 · 3 comments
Closed

go/types: comparison of Defined (Named) types fails #35265

guzenok opened this issue Oct 31, 2019 · 3 comments

Comments

@guzenok
Copy link

@guzenok guzenok commented Oct 31, 2019

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

go version go1.13.3 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
GO111MODULE=""                                                                                                                                                                                              
GOARCH="amd64"                                                                                                                                                                                              
GOBIN=""                                                                                                                                                                                                    
GOCACHE="/home/fabel/.cache/go-build"                                                                                                                                                                       
GOENV="/home/fabel/.config/go/env"                                                                                                                                                                          
GOEXE=""                                                                                                                                                                                                    
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/fabel/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/fabel/go/src/github.com/golang/go/src/go.mod"
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 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build619135294=/tmp/go-build -gno-record-gcc-switches"

What did you do?

package main

import (
	"fmt"
	"go/importer"
	"go/token"
	"go/types"
)

const importThis = "."

type SType struct{}

var SInstance SType

func main() {
	theScope := importScope(importThis)
	typeofSType := theScope.Lookup("SType").Type()

	theSameScope := importScope(importThis)
	typeofSInstance := theSameScope.Lookup("SInstance").Type()

	if types.AssignableTo(typeofSInstance, typeofSType) {
		fmt.Println("EXPECTED.")
	} else {
		fmt.Println("UNEXPECTED!")
	}
}

func importScope(importpath string) *types.Scope {
	goImporter := importer.ForCompiler(token.NewFileSet(), "source", nil)
	pkg, err := goImporter.Import(importpath)
	if err != nil {
		panic(`run it from source dir to make const "importThis" true`)
	}

	return pkg.Scope()
}

What did you expect to see?

EXPECTED.

What did you see instead?

UNEXPECTED!
@gopherbot
Copy link

@gopherbot gopherbot commented Oct 31, 2019

Change https://golang.org/cl/204477 mentions this issue: go/types: Checker.identical0() fix

Loading

@ALTree
Copy link
Member

@ALTree ALTree commented Oct 31, 2019

Loading

@griesemer griesemer self-assigned this Oct 31, 2019
@griesemer griesemer changed the title go/types: comparing go/types: comparison of Defined (Named) types fails Oct 31, 2019
@griesemer
Copy link
Contributor

@griesemer griesemer commented Oct 31, 2019

This is working as intended.

The bug is not in go/types, it is in the sample program provided. During a single compilation, or in this program, for the duration of the program, go/types Objects and Types must be canonicalized for them to be directly comparable. Specifically, this means, that one cannot mix and match Objects imported by different importer because it is the responsibility of an importer to canonicalize Objects and Types.

The bug in the sample program provided is that importScope creates a new importer with each call instead of reusing one. The fix is easy: create the importer only once and reuse it: This program works as expected:

package main

import (
	"fmt"
	"go/importer"
	"go/token"
	"go/types"
)

const importThis = "."

type SType struct{}

var SInstance SType

func main() {
	theScope := importScope(importThis)
	typeofSType := theScope.Lookup("SType").Type()

	theSameScope := importScope(importThis)
	typeofSInstance := theSameScope.Lookup("SInstance").Type()

	if types.AssignableTo(typeofSInstance, typeofSType) {
		fmt.Println("EXPECTED.")
	} else {
		fmt.Println("UNEXPECTED!")
	}
}

// A single goImporter must be used for all imports to ensure
// identical Objects and types are properly canonicalized.
var goImporter = importer.ForCompiler(token.NewFileSet(), "source", nil)

func importScope(importpath string) *types.Scope {
	// goImporter := importer.ForCompiler(token.NewFileSet(), "source", nil) // <<< THIS IS THE BUG
	pkg, err := goImporter.Import(importpath)
	if err != nil {
		panic(`run it from source dir to make const "importThis" true`)
	}

	return pkg.Scope()
}

Loading

@griesemer griesemer closed this Oct 31, 2019
@golang golang locked and limited conversation to collaborators Oct 30, 2020
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.

4 participants