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

Closed
tinne26 opened this issue Feb 7, 2022 · 9 comments
Closed

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

tinne26 opened this issue Feb 7, 2022 · 9 comments
Assignees
Labels
NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Milestone

Comments

@tinne26
Copy link

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

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 Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Feb 7, 2022
@ianlancetaylor ianlancetaylor added this to the Go1.19 milestone Feb 7, 2022
@ianlancetaylor
Copy link
Contributor

CC @griesemer

@mymmrac
Copy link

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

@mymmrac Yes, that is expected in Go 1.18.

@mymmrac
Copy link

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)

@ianlancetaylor
Copy link
Contributor

Rolling forward to 1.20. Please comment if you disagree. Thanks.

@ianlancetaylor ianlancetaylor modified the milestones: Go1.19, Go1.20 Jun 24, 2022
@griesemer griesemer self-assigned this Jun 24, 2022
@griesemer griesemer added NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. and removed NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Jun 24, 2022
@griesemer griesemer modified the milestones: Go1.20, Go1.21 Nov 15, 2022
@griesemer
Copy link
Contributor

No progress on this issue. Rolling forward to 1.22.

@griesemer griesemer modified the milestones: Go1.21, Go1.22 May 16, 2023
@griesemer
Copy link
Contributor

Rolling forward to 1.23.

@griesemer griesemer modified the milestones: Go1.22, Go1.23 Oct 31, 2023
@griesemer
Copy link
Contributor

This is tied to the requirement that range expressions must have a core type.
There's a larger issue (#63940) for investigating whether we can avoid the use of core types altogether - that would also require addressing this issue, one way or the other.
Closing in favor of #63940.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Projects
Status: Done
Development

No branches or pull requests

4 participants