-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: allow eliding interface{ } in constraint literals #48424
Comments
CC @griesemer |
This is an interesting idea and we had (internally to the Go team) discussed essentially the same thing: writing a type expression In any case, the proposal would have to be generalized a bit. For instance, we would want to say |
If we do this, I don't think we should automatically insert a func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, cmp func(V1, V2) bool) bool
func Clone[S ~[]T, T any](s S) S |
In my imagination it's not "type set expression hoisted to type parameter list level", hence no | or ~. I intended to keep more complex and nuanced constraint definitions inside interfaces. I see it as "expand non-interface type into its sole useful constraint form". It is admittedly some amount of magic. |
I know it's probably too late for syntax changes re. constraints, but I personally would have preferred this:
With
No tilde, and types like |
@fzipp If we want to make this change, let's keep this issue tightly focused on this specific change, not on a discussion of possible alternative syntaxes. Thanks. |
We might be able to say that a constraint is simply a type set. A type set may be expressed through an interface (as we do now), but it may also be a type expression of the form Or, looking from a slightly different angle, we could say that writing |
Agree with @ianlancetaylor about the ~ not being tied to the shortening. It's already the case that [C interface{X}] and [C interface{interface{X}}] are the same, And it would let us remove constraints.Map, constraints.Slice, etc. @griesemer will prototype and prepare a CL showing the effect on code. |
I'm ok with it if this is the preferred variant. |
This proposal has been added to the active column of the proposals project |
This is definitely a readability win: I couldn't understand why the |
@rsc I'm not tracking all the (apparently more numerous than I thought) proposals related to generics, so I'd like to ask, if that's ok: will the discussion around this proposal temporarily suspend introduction of the |
@akavel I'm confident that this proposal will be either accepted or declined before Go 1.18. If accepted, we should then consider removing |
Change https://golang.org/cl/353133 mentions this issue: |
Change https://golang.org/cl/353139 mentions this issue: |
Change https://golang.org/cl/353389 mentions this issue: |
Change https://golang.org/cl/353395 mentions this issue: |
Change https://golang.org/cl/353396 mentions this issue: |
…amTests Matching change for the corresponding file in CL 353389. To make the builds pass for now. For golang/go#48424. Change-Id: Id66837957ffec4e4b19faa0337a7587ea8bd6125 Reviewed-on: https://go-review.googlesource.com/c/tools/+/353395 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> gopls-CI: kokoro <noreply+kokoro@google.com>
…terals This CL permits an arbitrary type as well as the type sets ~T and A|B in constraint position, without the need of a surrrounding interface. For instance, the type parameter list [P interface{ ~map[K]V }, K comparable, V interface{ ~string }] may be written as [P ~map[K]V, K comparable, V ~string] The feature must be enabled explicitly with the AllowTypeSets mode and is only available if AllowGenerics is set as well. For #48424. Change-Id: Ic70bb97a49ff75e67e040853eac10e6aed0fef1a Reviewed-on: https://go-review.googlesource.com/c/go/+/353133 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
…nterfaces When collecting type parameters, wrap constraint literals of the form ~T or A|B into interfaces so the type checker doesn't have to deal with these type set expressions syntactically anywhere else but in interfaces (i.e., union types continue to appear only as embedded elements in interfaces). Since a type constraint doesn't need to be an interface anymore, we can remove the respective restriction. Instead, when accessing the constraint interface via TypeParam.iface, wrap non-interface constraints at that point and update the constraint so it happens only once. By computing the types sets of all type parameters at before the end of type-checking, we ensure that type constraints are in their final form when accessed through the API. For #48424. Change-Id: I3a47a644ad4ab20f91d93ee39fcf3214bb5a81f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/353139 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This change enables the relaxed syntax for constraint literals as proposed in issue #48424 and adds a simple smoke test for the compiler. (Most of the relevant changes are in the syntax and types2 package which have more extensive tests for this.) This makes it possible to experiment with the new syntax while we contemplate the fate of #48424. If #48424 is accepted, this change can remain. If #48424 is not accepted, reverting this CL will remove this feature in the compiler. For #48424. Change-Id: I624fbb37c2f616ee9ad692e17e4fc75c9d5b06e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/353389 Trust: Robert Griesemer <gri@golang.org> Trust: Dan Scales <danscales@google.com> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> Reviewed-by: Dan Scales <danscales@google.com>
Provide an accessor for clients, and don't print the interface around implicitly wrapped embedded types. For #48424. Change-Id: Ib2c76315508fc749ea4337d52e13d17de80e04da Reviewed-on: https://go-review.googlesource.com/c/go/+/353396 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This is now implemented in the compiler in the master branch at tip so we can explore this in practice. Note that this proposal has not been accepted yet, so don't write code that you expect to remain valid a month from now... Only the compiler understands this notation at the moment, tools such as gofmt, vet, etc. cannot handle this yet. If the proposal is not accepted, we can quickly disable the feature by changing a flag in the compiler. |
No change in consensus, so accepted. 🎉 |
Change https://golang.org/cl/355709 mentions this issue: |
The respective issue has been accepted, so we can always accept constraint literals with omitted interfaces. For #48424. Change-Id: Ia3d325401252a5a22d5ffa98d2ae6af73178dec0 Reviewed-on: https://go-review.googlesource.com/c/go/+/355709 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This has been implemented in the compiler and go/types and go/print. @findleyr is there more to do on the std library side or can we close this (and track additional work separately)? |
@griesemer I've filed #49040 to track adding the implicit bit to export data, so I think this issue can be closed. |
Change https://golang.org/cl/357796 mentions this issue: |
Add a new interface method, MarkImplicit, to allow marking interfaces as implicit from outside the type-checker. This is necessary so that we can capture the implicit bit in export data, and use it from importers. For #48424 For #49040 Change-Id: I999aba2a298f92432326d7ccbd87fe133a2e1a72 Reviewed-on: https://go-review.googlesource.com/c/go/+/357796 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
Change https://golang.org/cl/359258 mentions this issue: |
Now that we permit arbitrary types as constraints, we no longer need them. For #48424 Change-Id: I15fef26a563988074650cb0801895b002c44148a Reviewed-on: https://go-review.googlesource.com/c/go/+/359258 Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
I first proposed this in the slice functions discussion but didn't get anywhere. Admittedly I was a little off-topic. Imagine my surprise just now when I find the official Generics Tutorial is using union syntax directly in type arguments, and then the Proposal is using I had been resigned to using In terms of the philosophy mentioned by @griesemer :
Both work, my opinion is that the former is superior. A type is The real litmus test is how well devs work with that mental model. I for one love it. |
Shouldn't there be a func foo[T int](t T) {
fmt.Println(t)
} Unless I'm missing something, the type parameter doesn't provide any benefit and the function could as well be declared as func foo(i int) {
fmt.Println(i)
} |
@jub0bs please feel free to open a proposal for such a vet check. Vet has three conditions for new checks: I suspect that what you suggests meets the Correctness and Precision requirements, but may not meet the Frequency requirement. This could be discussed in a proposal. |
I propose an additional rule for constraints in type parameter lists:
[T nonInterfaceType]
≡[T interface{~nonInterfaceType}]
Rationale:
All functions of the proposed
maps
package (#47649) and most functions of theslices
package (#45955, #47203) currently use constraints from theconstraints
package (#45458) for maximum generality. A hypotheticalchans
package would probably be similar (there's already a proposal forconstraints.{ReadOnlyChan|WriteOnlyChan}
: #48366). Some excerpts:With this proposal these would become:
The benefit:
constraints.{Slice|Map|Chan|ReadOnlyChan|WriteOnlyChan}
would not be necessary at all.map[K]V
,[]T
,chan T
,<-chan T
,chan<- T
and their accompanying constraints.This proposal stems from the discussion under #47330 (reply in thread)
Summary:
The text was updated successfully, but these errors were encountered: