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: union of embeddings should not eagerly evaluate parameters #49053

Closed
extemporalgenome opened this issue Oct 19, 2021 · 1 comment
Closed

Comments

@extemporalgenome
Copy link
Contributor

@extemporalgenome extemporalgenome commented Oct 19, 2021

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

$ go version
go version devel go1.18-eba0e866fa Mon Oct 18 22:56:07 2021 +0000 linux/amd64

Does this issue reproduce with the latest release?

N/A (tip)

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN="/home/kevin/usr/bin"
GOCACHE="/home/kevin/.cache/go-build"
GOENV="/home/kevin/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/kevin/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/kevin/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/kevin/goroot"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/kevin/goroot/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="devel go1.18-eba0e866fa Mon Oct 18 22:56:07 2021 +0000"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/kevin/src/sandbox/go2/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-build2350545574=/tmp/go-build -gno-record-gcc-switches"

What did you do?

While exploring the tip generics implementation, I attempted to determine if I could express "precise numeric conversions" (conversions that cannot cause overflow or loss of precision, such as int8 -> int16, but not the reverse).

package main

import "fmt"

type ConvertTo[To Integer] interface {
  I8[To] | I16[To]
}

type Integer interface {
  ~int8 | ~int16 | ~int32 | ~int64 | ~int
}

type I8[To I8Plus] interface {
  ~int8
}

type I8Plus interface {
  ~int8 | ~int16 | ~int32 | ~int64 | ~int
}

type I16[To I16Plus] interface {
  ~int16
}

type I16Plus interface {
  ~int16 | ~int32 | ~int64 | ~int
}

func Convert[From ConvertTo[To], To Integer](f From) To {
  return To(f)
}

func Print[T any](v T) {
  fmt.Printf("%T(%[1]v)\n", v)
}

func main() {
  type MyInt8 int8
  t := int8(11)
  u := Convert[int8, MyInt8](t)
  Print(u)
}

What did you expect to see?

Concerning:

type ConvertTo[To Integer] interface {
  I8[To] | I16[To]
}

I would expect the instantiation to be valid if the To parameter is valid for any of the embedded constraints within the union. I would not expect that the To parameter would need to validate against all possible embedded constraints for the same reason that a type does not need to satisfy all of int8 | int16 simultaneously.

What did you see instead?

When attempting to run, I see:

go run main.go
# command-line-arguments
./main.go:6:16: To does not satisfy I16Plus
@ALTree ALTree changed the title Generics: Union of embeddings should not eagerly evaluate parameters cmd/compile: union of embeddings should not eagerly evaluate parameters Oct 19, 2021
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Oct 20, 2021

In your example code, I16 can only be implemented by a type argument that satisfies I16Plus. ConvertTo can be implemented by a type argument that satisfies Integer. If someone writes ConvertTo[int8] that is valid according to the constraint of ConvertTo. ConvertTo then tries to instantiate I16[int8]. But int8 does not satisfy I16Plus, so that instantiation will fail. Therefore, ConvertTo is not a valid interface, and the compiler reports an error.

I think you are suggesting that the compiler should ignore the union term I16[To] for cases where To does not satisfy the constraint of the I16 type parameter. That is not how the current proposal works. And it would be a very subtle change, similar to C++ SFINAE. I think that it would permit certain kinds of conditional type matching during instantiation. That is probably not a feature that we want in Go.

In any case, such a feature would require a new proposal, describing the exact change proposed. I'm going to close this issue because the compiler is behaving correctly according to the currently accepted generics proposal.

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants