]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] go/types: disallow ~T where T is a defined type or an interface
authorRob Findley <rfindley@google.com>
Thu, 10 Jun 2021 16:23:40 +0000 (12:23 -0400)
committerRobert Findley <rfindley@google.com>
Thu, 17 Jun 2021 02:15:03 +0000 (02:15 +0000)
This is a straightforward port of CL 324570 to go/types.

Change-Id: I1395775a1d21a903a57e0cefc4e240cfa2bb8e97
Reviewed-on: https://go-review.googlesource.com/c/go/+/326684
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>
src/go/types/testdata/check/typeinst2.go2
src/go/types/testdata/examples/constraints.go2
src/go/types/testdata/fixedbugs/issue39634.go2
src/go/types/union.go

index a4c9f58c09739a2e6c39bc3499cc47ba8006b61f..ab56ccafc91e755aaa4136fba8d472ea755b8b7a 100644 (file)
@@ -176,12 +176,12 @@ type _ interface {
 // Interface type lists can contain any type, incl. *Named types.
 // Verify that we use the underlying type to compute the operational type.
 type MyInt int
-func add1[T interface{~MyInt}](x T) T {
+func add1[T interface{MyInt}](x T) T {
        return x + 1
 }
 
 type MyString string
-func double[T interface{~MyInt | ~MyString}](x T) T {
+func double[T interface{MyInt|MyString}](x T) T {
        return x + x
 }
 
index 61992e4c2a8e408197bccc1d1e11d404b6628530..d9805fe6940a9c665a9a712c63aef9130f0fa4af 100644 (file)
@@ -36,6 +36,15 @@ type (
        _ interface{int|interface /* ERROR cannot use interface */ {}}
 )
 
+type (
+       // Tilde is not permitted on defined types or interfaces.
+       foo int
+       bar interface{}
+       _ interface{foo}
+       _ interface{~ /* ERROR invalid use of ~ */ foo }
+       _ interface{~ /* ERROR invalid use of ~ */ bar }
+)
+
 // Multiple embedded union elements are intersected. The order in which they
 // appear in the interface doesn't matter since intersection is a symmetric
 // operation.
index 8decff5291e03b01c0ff0beb57f879656ee47b73..2a1367373f5ebb4ee9009256bc8f7418e139db4f 100644 (file)
@@ -36,8 +36,8 @@ func bar8[A foo8[A]](a A) {}
 func main8() {}
 
 // crash 9
-type foo9[A any] interface { ~ /* ERROR cannot use interface */ foo9 [A] }
-func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) }
+type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] }
+func _() { var _ = new(foo9 /* ERROR illegal cycle */ [int]) }
 
 // crash 12
 var u /* ERROR cycle */ , i [func /* ERROR used as value */ /* ERROR used as value */ (u, c /* ERROR undeclared */ /* ERROR undeclared */ ) {}(0, len /* ERROR must be called */ /* ERROR must be called */ )]c /* ERROR undeclared */ /* ERROR undeclared */
index 4eda874eb8ad41e40ca97e2d2d96f8d0ae228ef3..690b734d76d1399a38dbb6f7bbbb55f636c463f3 100644 (file)
@@ -109,17 +109,18 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type {
                        }
 
                        u := under(t)
-                       if tilde[i] {
-                               // TODO(rfindley) enable this check once we have converted tests
-                               // if !Identical(u, t) {
-                               //      check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t, u)
-                               // }
+                       if tilde[i] && !Identical(u, t) {
+                               check.errorf(x, _Todo, "invalid use of ~ (underlying type of %s is %s)", t, u)
+                               continue // don't report another error for t
                        }
                        if _, ok := u.(*Interface); ok {
+                               // A single type with a ~ is a single-term union.
                                check.errorf(atPos(pos), _Todo, "cannot use interface %s with ~ or inside a union (implementation restriction)", t)
+                               continue // don't report another error for t
                        }
 
                        // Complain about duplicate entries a|a, but also a|~a, and ~a|~a.
+                       // TODO(gri) We should also exclude myint|~int since myint is included in ~int.
                        if includes(types[:i], t) {
                                // TODO(rfindley) this currently doesn't print the ~ if present
                                check.softErrorf(atPos(pos), _Todo, "duplicate term %s in union element", t)