Skip to content

cmd/compile: type sets are not correctly deduced for type conversion on type params #63827

@nevkontakte

Description

@nevkontakte

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

Go Playground, 1.21

Does this issue reproduce with the latest release?

Yes

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

N/A, Go Playground

What did you do?

https://go.dev/play/p/Jhx6YGrz21s

What did you expect to see?

Both convert() and convert2() are accepted by the compiler and are semantically equivalent.

What did you see instead?

convert2() is rejected by the compiler: cannot convert x (variable of type srcType constrained by string) to type dstType: cannot convert string (in srcType) to type []elType (in dstType)

Details

The spec says the following about type conversions of type params:

Additionally, if T or x's type V are type parameters, x can also be converted to type T if one of the following conditions applies:

  • Both V and T are type parameters and a value of each type in V's type set can be converted to each type in T's type set.

Consider the following code:

type charLike interface{ byte | rune }

func convert2[elType charLike, srcType string, dstType []elType](x srcType) dstType {
	return dstType(x) // ERROR: cannot convert x (variable of type srcType constrained by string) to type dstType: cannot convert string (in srcType) to type []elType (in dstType)
}

Here srcType's type set should be just string, and dstType's type set is []rune|[]byte. As per spec, string can be converted to both []rune and []byte:

A non-constant value x can be converted to type T in any of these cases:

  • ...
  • x is a string and T is a slice of bytes or runes.

So, conversion should be allowed, assuming the compiler is able to correctly deduce type set for dstType.

The simplest example of the issue I was able to find:

func convert2[elType byte, dstType []elType](x string) dstType {
	return dstType(x) // ERROR: cannot convert x (variable of type string) to type dstType: cannot convert string to type []elType (in dstType)
}

The next step of eliminating elType makes the error disappear:

func convert2[dstType []byte](x string) dstType {
	return dstType(x)}

So it seems the compiler fails to flatten dstType's type set with indirection from elType.

Also, @Merovius was able to construct the following two semantically equivalent examples that hint that the issue is somehow specific to the type conversion operation:

Metadata

Metadata

Assignees

Labels

compiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

Status

Todo

Relationships

None yet

Development

No branches or pull requests

Issue actions