--- /dev/null
+pkg go/types, func Satisfies(Type, *Interface) bool #56548
SymABIs string "help:\"read symbol ABIs from `file`\""
TraceProfile string "help:\"write an execution trace to `file`\""
TrimPath string "help:\"remove `prefix` from recorded source file paths\""
- WB bool "help:\"enable write barrier\"" // TODO: remove
- AltComparable bool "help:\"enable alternative comparable semantics\"" // experiment - remove eventually
+ WB bool "help:\"enable write barrier\"" // TODO: remove
+ OldComparable bool "help:\"enable old comparable semantics\"" // TODO: remove for Go 1.21
PgoProfile string "help:\"read profile from `file`\""
// Configuration derived from flags; not a flag itself.
},
Importer: &importer,
Sizes: &gcSizes{},
- AltComparableSemantics: base.Flag.AltComparable, // experiment - remove eventually
+ OldComparableSemantics: base.Flag.OldComparable, // default is new comparable semantics
}
info := &types2.Info{
StoreTypesInSyntax: true,
// for unused imports.
DisableUnusedImportCheck bool
- // If AltComparableSemantics is set, ordinary (non-type parameter)
- // interfaces satisfy the comparable constraint.
- AltComparableSemantics bool
+ // If OldComparableSemantics is set, ordinary (non-type parameter)
+ // interfaces do not satisfy the comparable constraint.
+ // TODO(gri) remove this flag for Go 1.21
+ OldComparableSemantics bool
}
func srcimporter_setUsesCgo(conf *Config) {
return (*Checker)(nil).implements(V, T, false, nil)
}
+// Satisfies reports whether type V satisfies the constraint T.
+//
+// The behavior of Satisfies is unspecified if V is Typ[Invalid] or an uninstantiated
+// generic type.
+func Satisfies(V Type, T *Interface) bool {
+ return (*Checker)(nil).implements(V, T, true, nil)
+}
+
// Identical reports whether x and y are identical types.
// Receivers of Signature types are ignored.
func Identical(x, y Type) bool {
flags := flag.NewFlagSet("", flag.PanicOnError)
flags.StringVar(&conf.GoVersion, "lang", "", "")
flags.BoolVar(&conf.FakeImportC, "fakeImportC", false, "")
- flags.BoolVar(&conf.AltComparableSemantics, "altComparableSemantics", false, "")
+ flags.BoolVar(&conf.OldComparableSemantics, "oldComparableSemantics", false, "")
if err := parseFlags(filenames[0], nil, flags); err != nil {
t.Fatal(err)
}
// Only check comparability if we don't have a more specific error.
checkComparability := func() bool {
+ if !Ti.IsComparable() {
+ return true
+ }
// If T is comparable, V must be comparable.
- // For constraint satisfaction, use dynamic comparability for the
- // alternative comparable semantics such that ordinary, non-type
- // parameter interfaces implement comparable.
- dynamic := constraint && check != nil && check.conf.AltComparableSemantics
- if Ti.IsComparable() && !comparable(V, dynamic, nil, nil) {
+ // If V is strictly comparable, we're done.
+ if comparable(V, false /* strict comparability */, nil, nil) {
+ return true
+ }
+ // If check.conf.OldComparableSemantics is set (by the compiler or
+ // a test), we only consider strict comparability and we're done.
+ // TODO(gri) remove this check for Go 1.21
+ if check != nil && check.conf.OldComparableSemantics {
if cause != nil {
*cause = check.sprintf("%s does not implement comparable", V)
}
return false
}
- return true
+ // For constraint satisfaction, use dynamic (spec) comparability
+ // so that ordinary, non-type parameter interfaces implement comparable.
+ if constraint && comparable(V, true /* spec comparability */, nil, nil) {
+ // V is comparable if we are at Go 1.20 or higher.
+ if check == nil || check.allowVersion(check.pkg, 1, 20) {
+ return true
+ }
+ if cause != nil {
+ *cause = check.sprintf("%s to implement comparable requires go1.20 or later", V)
+ }
+ return false
+ }
+ if cause != nil {
+ *cause = check.sprintf("%s does not implement comparable", V)
+ }
+ return false
}
// V must also be in the set of types of T, if any.
// for unused imports.
DisableUnusedImportCheck bool
- // If altComparableSemantics is set, ordinary (non-type parameter)
- // interfaces satisfy the comparable constraint.
- altComparableSemantics bool
+ // If oldComparableSemantics is set, ordinary (non-type parameter)
+ // interfaces do not satisfy the comparable constraint.
+ // TODO(gri) remove this flag for Go 1.21
+ oldComparableSemantics bool
}
func srcimporter_setUsesCgo(conf *Config) {
return (*Checker)(nil).implements(V, T, false, nil)
}
+// Satisfies reports whether type V satisfies the constraint T.
+//
+// The behavior of Satisfies is unspecified if V is Typ[Invalid] or an uninstantiated
+// generic type.
+func Satisfies(V Type, T *Interface) bool {
+ return (*Checker)(nil).implements(V, T, true, nil)
+}
+
// Identical reports whether x and y are identical types.
// Receivers of Signature types are ignored.
func Identical(x, y Type) bool {
flags := flag.NewFlagSet("", flag.PanicOnError)
flags.StringVar(&conf.GoVersion, "lang", "", "")
flags.BoolVar(&conf.FakeImportC, "fakeImportC", false, "")
- flags.BoolVar(addrAltComparableSemantics(&conf), "altComparableSemantics", false, "")
+ flags.BoolVar(addrOldComparableSemantics(&conf), "oldComparableSemantics", false, "")
if err := parseFlags(filenames[0], srcs[0], flags); err != nil {
t.Fatal(err)
}
return int(v.FieldByName("go116code").Int())
}
-// addrAltComparableSemantics(conf) returns &conf.altComparableSemantics (unexported field).
-func addrAltComparableSemantics(conf *Config) *bool {
+// addrOldComparableSemantics(conf) returns &conf.oldComparableSemantics (unexported field).
+func addrOldComparableSemantics(conf *Config) *bool {
v := reflect.Indirect(reflect.ValueOf(conf))
- return (*bool)(v.FieldByName("altComparableSemantics").Addr().UnsafePointer())
+ return (*bool)(v.FieldByName("oldComparableSemantics").Addr().UnsafePointer())
}
// TestManual is for manual testing of a package - either provided
// Only check comparability if we don't have a more specific error.
checkComparability := func() bool {
+ if !Ti.IsComparable() {
+ return true
+ }
// If T is comparable, V must be comparable.
- // For constraint satisfaction, use dynamic comparability for the
- // alternative comparable semantics such that ordinary, non-type
- // parameter interfaces implement comparable.
- dynamic := constraint && check != nil && check.conf.altComparableSemantics
- if Ti.IsComparable() && !comparable(V, dynamic, nil, nil) {
+ // If V is strictly comparable, we're done.
+ if comparable(V, false /* strict comparability */, nil, nil) {
+ return true
+ }
+ // If check.conf.OldComparableSemantics is set (by the compiler or
+ // a test), we only consider strict comparability and we're done.
+ // TODO(gri) remove this check for Go 1.21
+ if check != nil && check.conf.oldComparableSemantics {
if cause != nil {
*cause = check.sprintf("%s does not implement comparable", V)
}
return false
}
- return true
+ // For constraint satisfaction, use dynamic (spec) comparability
+ // so that ordinary, non-type parameter interfaces implement comparable.
+ if constraint && comparable(V, true /* spec comparability */, nil, nil) {
+ // V is comparable if we are at Go 1.20 or higher.
+ if check == nil || check.allowVersion(check.pkg, 1, 20) {
+ return true
+ }
+ if cause != nil {
+ *cause = check.sprintf("%s to implement comparable requires go1.20 or later", V)
+ }
+ return false
+ }
+ if cause != nil {
+ *cause = check.sprintf("%s does not implement comparable", V)
+ }
+ return false
}
// V must also be in the set of types of T, if any.
+// -oldComparableSemantics
+
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// -oldComparableSemantics
+
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// -oldComparableSemantics
+
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// -altComparableSemantics
-
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
--- /dev/null
+// -lang=go1.19
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f1[_ comparable]() {}
+func f2[_ interface{ comparable }]() {}
+
+type T interface{ m() }
+
+func _[P comparable, Q ~int, R any]() {
+ _ = f1[int]
+ _ = f1[T /* ERROR T to implement comparable requires go1\.20 or later */]
+ _ = f1[any /* ERROR any to implement comparable requires go1\.20 or later */]
+ _ = f1[P]
+ _ = f1[Q]
+ _ = f1[R /* ERROR R does not implement comparable */]
+
+ _ = f2[int]
+ _ = f2[T /* ERROR T to implement comparable requires go1\.20 or later */]
+ _ = f2[any /* ERROR any to implement comparable requires go1\.20 or later */]
+ _ = f2[P]
+ _ = f2[Q]
+ _ = f2[R /* ERROR R does not implement comparable */]
+}
--- /dev/null
+// -oldComparableSemantics
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f1[_ comparable]() {}
+func f2[_ interface{ comparable }]() {}
+
+type T interface{ m() }
+
+func _[P comparable, Q ~int, R any]() {
+ _ = f1[int]
+ _ = f1[T /* ERROR T does not implement comparable */]
+ _ = f1[any /* ERROR any does not implement comparable */]
+ _ = f1[P]
+ _ = f1[Q]
+ _ = f1[R /* ERROR R does not implement comparable */]
+
+ _ = f2[int]
+ _ = f2[T /* ERROR T does not implement comparable */]
+ _ = f2[any /* ERROR any does not implement comparable */]
+ _ = f2[P]
+ _ = f2[Q]
+ _ = f2[R /* ERROR R does not implement comparable */]
+}