-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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: document/explain which interfaces implement comparable
#50646
Comments
A little more context: I am updating github.com/bobg/modver to be generics-aware. This package can compare two versions of a Go module and tell whether a major, minor, or patchlevel version-number bump is needed, according to semver rules. If two versions of a Go object differ only in the constraint on a type parameter, what should the result be? The answer depends on the type set implied by the constraint. If the two type sets are identical, the result should be I had hoped to use Thanks... |
In the current language no variable can have the type The question you want to ask seems like a reasonable one but I don't know whether the go/types package supports answering that question yet. |
|
When we check whether a (a value of) type If In short, this is not a bug but simply a consequence of existing rules. Leaving this issue open for now so we can close it with a CL that adds some more tests. |
comparable
Change https://golang.org/cl/380654 mentions this issue: |
comparable
comparable
OK, I can buy that (though I don't love it). But there's something that distinguishes type X[K, V any] map[K]V Is that distinction surfaced in the stdlib? What is the right way to detect it? Will an explicit call to |
In this code snippet, the type of
There won't be a What is missing in the in-progress spec is not extra rules for this, just a sentence highlighting the fact that all interfaces implement |
It is some weird to view It is not a problem to view Maybe the |
Nobody is saying that However, values of type |
To put it another way, this code, which instantiates a type parameter of type func Eq[T comparable](a, b T) bool {
return a == b
}
func EqAny(x, y any) bool {
return Eq(x, y)
} |
For #50646. Change-Id: I7420545556e0df2659836364a62ce2c32ad7a8b1 Reviewed-on: https://go-review.googlesource.com/c/go/+/380654 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This listens some weird. An interface value may never box another interface value. |
func Eq[T comparable](a, b T) bool {
return a == b
}
func EqAny(x, y any) bool {
return Eq(x, y)
} This example is legal because On the contrary, the following code should not work: func Eq(a, b comparable) bool {
return a == b
}
func EqAny(x, y any) bool {
return Eq(x, y)
} I understand that a type constraint might be directly used as a value type (sum type) later. Edit: here "subset" and "superset" mean rule set. If they mean type set, then |
I disagree. This code works today: func EqIface(x, y any) bool {
return x == y
} That seems basically the same as the version that you wrote. |
Different from a method set, a type Comparable interface {
==(another Comparable) bool
} |
Yes, we could have gone that way in the language. But we didn't. (Part of the reason we didn't is that the interface definition you wrote permits using the |
I agree my above operator method definition is not perfect. It is just used to make the explanation. |
And if var x any = []int{}
var c, ok = x.(comparable)
print(ok) |
By the rules of type assertions, I think your code would have to print You're right that it's an interesting case. |
In the current implementation rule, if |
Change https://golang.org/cl/381435 mentions this issue: |
This CL copies (and adjusts as needed) the logic for error reporting from operand.assignableTo to Checker.implements in the case of a missing method failure and assignment to an interface pointer. Preparation for using Checker.implements in operand.assignableTo rather than implementing the same logic twice. This also leads to better errors from Checker.implements as it's using the same logic we already use elsewhere. For #50646. Change-Id: I199a1e02cf328b222ae52c10131db871539863bf Reviewed-on: https://go-review.googlesource.com/c/go/+/381434 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
Now that we have the detailed error reporting in Checker.implements we don't need it anymore in operand.assignableTo and can simply call Checker.implements. This also more directly matches the spec. For #50646. Change-Id: Ic44ced999c75be6cc9edaab01177ee0495147ea1 Reviewed-on: https://go-review.googlesource.com/c/go/+/381435 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
Change https://golang.org/cl/381896 mentions this issue: |
- Use the correct predicate in Checker.implements: for interfaces we cannot use the API Comparable because it always returns true for all non-type parameter interface types: Comparable simply answers if == and != is permitted, and it's always been permitted for interfaces. Instead we must use Interface.IsComparable which looks at the type set of an interface. - When comparing interfaces for identity, we must also consider the whether the type sets have the comparable bit set. With this change, `any` doesn't implement `comparable` anymore. This only matters for generic functions and types, and the API functions. It does mean that for now (until we allow type-constrained interfaces for general non-constraint use, at some point in the future) a type parameter that needs to be comparable cannot be instantiated with an interface anymore. For #50646. Change-Id: I7e7f711bdcf94461f330c90509211ec0c2cf3633 Reviewed-on: https://go-review.googlesource.com/c/go/+/381254 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This is now fixed in the type checker. What is outstanding is the documentation in the spec. Not a release blocker anymore. |
@griesemer "... This is something we cannot change." |
For #50646. Fixes #50791. Change-Id: I8fec25ae3f0280c5b5a778011d23842b886ba79e Reviewed-on: https://go-review.googlesource.com/c/go/+/381896 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
@tinytina2021 I'm not sure I follow: we cannot change the behavior of |
The implementation of |
@griesemer Just to flag, the change so that It kinda seems like this change has been made a little last-minute and without particularly widespread discussion, but may have a fairly significant impact on people's ability to use generics in Go For example, when using golang-set, it's pretty reasonable that you might want to make a set containing any comparable type - e.g.: NewSetFromSlice[any](
[]any{
1,
2,
3,
"test",
},
) The code cannot be written as So as far as I can see, it is no longer possible to write this code at all - though maybe I'm missing something obvious? If you're firm that Honestly, this seems significant enough to be a release blocker, although it probably could be fixed later without a breaking change Edit: opened as a new issue - #51257 - as I appreciate this one has been closed for a couple of weeks now |
I think the correct answer here is to allow |
Change https://go.dev/cl/401874 mentions this issue: |
For golang#50646. Change-Id: I7420545556e0df2659836364a62ce2c32ad7a8b1 Reviewed-on: https://go-review.googlesource.com/c/go/+/380654 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
https://go.dev/play/p/S-ijx-XOlu8?v=gotip
What did you expect to see?
true
false
That is, I (naively?) expected the same check that prevents me using non-comparable types as map keys to tell me that I cannot assign a value of an unconstrained type to a variable of a comparable type.
What did you see instead?
true
true
The text was updated successfully, but these errors were encountered: