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/go: go vet reports error: impossible type assertion: no type can implement both... for generic interface #50658

Closed
thomascoquet opened this issue Jan 17, 2022 · 8 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. release-blocker
Milestone

Comments

@thomascoquet
Copy link

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

1.18beta1

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

go env Output
$ go env
GO111MODULE="auto"
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/thomascoquet/.cache/go-build"
GOENV="/home/thomascoquet/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/thomascoquet/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/thomascoquet/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/thomascoquet/sdk/go1.18beta1"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/thomascoquet/sdk/go1.18beta1/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.18beta1"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/thomascoquet/Work/gobug/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 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build724234361=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I am using a generic interface the following way:

package gogenerics

import "fmt"

type Float interface {
	float32 | float64
}

type Doer[T Float] interface {
	Do() T
}

func Specialize[T Float](v Doer[T]) {
	switch v.(type) {
	case Doer[float32]:
		fmt.Println("float32!")
	case Doer[float64]:
		fmt.Println("float64!")
	}
}

What did you expect to see?

No error message.

What did you see instead?

When building or using go test ./..., I have the following message:

impossible type assertion: no type can implement both gogenerics.Doer[T] and gogenerics.Doer[float32] (conflicting types for Do method)

The error message also appears in VSCode (with the syntax highlighter using gopls with generics enabled).

I must emphasize that this code works perfectly well if imported from other modules ; the only isssue is when using the module "from itself".

@ianlancetaylor ianlancetaylor changed the title go/compile: impossible type assertion: no type can implement both... for generic interface cmd/compile: impossible type assertion: no type can implement both... for generic interface Jan 17, 2022
@ianlancetaylor
Copy link
Contributor

CC @griesemer @findleyr

I agree that it doesn't seem like this code should have an error.

@ianlancetaylor ianlancetaylor added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Jan 17, 2022
@ianlancetaylor ianlancetaylor added this to the Go1.18 milestone Jan 17, 2022
@griesemer griesemer self-assigned this Jan 18, 2022
@griesemer griesemer changed the title cmd/compile: impossible type assertion: no type can implement both... for generic interface cmd/go: go vet reports error: impossible type assertion: no type can implement both... for generic interface Jan 18, 2022
@griesemer
Copy link
Contributor

I can only reproduce this with go vet. The compilers and type checkers don't have a problem with this code. Temporary work-around: to run (any) tests, you can use go test -vet=off ./... .

@griesemer griesemer assigned timothy-king and unassigned griesemer Jan 18, 2022
@griesemer
Copy link
Contributor

cc: @findleyr

@findleyr
Copy link
Contributor

Yes, this looks like a problem with x/tools/go/analysis/passes/ifaceassert.

Thank you for filing. We will investigate.

@findleyr findleyr self-assigned this Jan 18, 2022
@timothy-king
Copy link
Contributor

I can confirm that I can reproduce with gotip test ./... at head (go1.18-50869f377fd).

ATM ifaceassert is essentially just delegating the decision for whether in a cast from V to U if V is an implementation of U to (go/types).MissingMethod. Here V is example.com/m.Doer[T] and U is example.com/m.Doer[float64]. Either this MissingMethod needs to be extended or we need to modify the detection logic in ifaceassert.

In this context, I think what we want to know is whether there does not exist a type instantiations s.t. V is an implementation of U. @griesemer and @findleyr how feasible is this to check?

Here is an example to showcase that we care about both potentially being type parameters.

func Specialize2[T Float, U Float](v Doer[T]) {
	switch v.(type) {
	case Doer[U]:
		fmt.Println("same!")
	}
}

A quick-n-dirty solution is to not check interfaces that contain any type parameters in ifaceassert. Thoughts?

Code: https://cs.opensource.google/go/x/tools/+/refs/tags/v0.1.8:go/analysis/passes/ifaceassert/ifaceassert.go;l=54

@findleyr
Copy link
Contributor

Hmm. This is rather tricky. In order to make it possible for tools to do this type of analysis correctly, we'd need to expose some sort of unification API. In this case, we'd need to see if there is a potential unification that allows this type assertion.

For 1.18, I think we should suppress the error message if either of the signatures in question are parameterized by type parameters.

@findleyr
Copy link
Contributor

@timothy-king submitted https://go.dev/cl/380014 to address this issue, so we can close this once we've re-vendored x/tools.

@gopherbot
Copy link

Change https://golang.org/cl/380777 mentions this issue: all: update vendored golang.org/x/tools

jproberts pushed a commit to jproberts/go that referenced this issue Jun 21, 2022
Update the vendored x/tools to pick up CL 380014, which updates the
ifaceassert vet analyzer to remove spurious errors for assertions
involving interfaces with type parameters.

This also picks up some superficial changes related to refactoring of
the x/tools/internal/typeparams API.

The following commands were used:

  go get -d golang.org/x/tools@master
  go mod tidy
  go mod vendor

Fixes golang#50658

Change-Id: I2f612fd186a1a260cab21860b192c9f6dc3f560f
Reviewed-on: https://go-review.googlesource.com/c/go/+/380777
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Tim King <taking@google.com>
@golang golang locked and limited conversation to collaborators Jun 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. release-blocker
Projects
None yet
Development

No branches or pull requests

6 participants