1
0
mirror of https://github.com/golang/go synced 2024-11-26 04:07:59 -07:00

[dev.typeparams] go/types: disallow ~T where T is a defined type or an interface

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>
This commit is contained in:
Rob Findley 2021-06-10 12:23:40 -04:00 committed by Robert Findley
parent 6237e441bc
commit 8115ae198d
4 changed files with 19 additions and 9 deletions

View 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
}

View 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.

View 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 */

View 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)