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

spec: can't range over parameter constrained by union type #51053

Open
tinne26 opened this issue Feb 7, 2022 · 5 comments
Open

spec: can't range over parameter constrained by union type #51053

tinne26 opened this issue Feb 7, 2022 · 5 comments
Labels
NeedsInvestigation
Milestone

Comments

@tinne26
Copy link

@tinne26 tinne26 commented Feb 7, 2022

What did you do?

Tried to execute this program: https://go.dev/play/p/JdOGVlCgCHh?v=gotip

It's fairly short, but to have the critical code here too:

type RuneIterable interface{ string | []rune }
func PrintEach[T RuneIterable](runes T) {
	for _, codePoint := range runes {
		fmt.Printf("next rune: '%s'\n", string(codePoint))
	}
}

What did you expect to see?

Expected it to compile and print the runes, as using any of the two types alone in the interface does actually work.

What did you see instead?

./prog.go:10:28: cannot range over runes (variable of type T constrained by RuneIterable) (T has no structural type)

Go build failed.

Additional notes

  • At first I expected this to work as a similar construct is shown at https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#composite-types-in-constraints where type byteseq interface { string | []byte } is used. But then I realized there's an ambiguity, as one might want to iterate a string as []byte or as []rune. It's not obvious what should even happen, and at least we should try to clarify it somewhere (maybe I missed something in the documentation).
  • Using range []rune(runes) works, but it's unclear the translation will be transparent.
  • Someone else also pointed on discord gophers that interface { string | chan string } would also be iterable but won't work. This might be another issue, I'm only mentioning it for context.
@ianlancetaylor ianlancetaylor changed the title generics: union type interface fails when the individual types work spec: can't range over parameter constrained by union type Feb 7, 2022
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Feb 7, 2022

Thanks. This is expected. We may try to tackle this for 1.19 or 1.20. The key issue is that we will need to develop some theory and mechanism for generic types that are not covered by the type parameter list. In this case the value type of range would be, as you say, either rune or byte.

If you look closely at the code in https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#composite-types-in-constraints you will see that it only uses range on values of type []T, which is not problematic. It does not use range on values of type T.

@ianlancetaylor ianlancetaylor added the NeedsInvestigation label Feb 7, 2022
@ianlancetaylor ianlancetaylor added this to the Go1.19 milestone Feb 7, 2022
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Feb 7, 2022

@mymmrac
Copy link

@mymmrac mymmrac commented Feb 21, 2022

Also, one case that can be investigated is range over map or slice type constrain, smallest example:

func f[SliceOrMapType map[int]int | []int](sliceOrMap SliceOrMapType) {
	for range sliceOrMap {}
}

Currently, reports an error:

cannot range over sliceOrMap (variable of type SliceOrMapType constrained by map[int]int|[]int) (SliceOrMapType has no core type)

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Feb 21, 2022

@mymmrac Yes, that is expected in Go 1.18.

@mymmrac
Copy link

@mymmrac mymmrac commented Feb 21, 2022

@mymmrac Yes, that is expected in Go 1.18.

Yep, I know, just wanted to mention it, because it seems to be related to this issue and it would be good to have similar fix in future releases)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation
Projects
None yet
Development

No branches or pull requests

3 participants