[dev.typeparams] go/types: embedding stand-alone type parameters is not permitted

This is a port of CL 334151 to go/types.

Fixes #47127

Change-Id: I57d69c498d2649a9e1657559e4c0271333096c88
Reviewed-on: https://go-review.googlesource.com/c/go/+/335082
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-07-16 20:57:10 -04:00 committed by Robert Findley
parent 82f875d735
commit 7e714f448e
8 changed files with 81 additions and 40 deletions

View file

@ -239,7 +239,7 @@ func _[T interface{ ~func() }](f T) {
type sliceOf[E any] interface{ ~[]E } type sliceOf[E any] interface{ ~[]E }
func append[T interface{}, S sliceOf[T], T2 interface{ T }](s S, t ...T2) S func append[T interface{}, S sliceOf[T], T2 interface{}](s S, t ...T2) S
var f func() var f func()
var cancelSlice []context.CancelFunc var cancelSlice []context.CancelFunc

View file

@ -11,19 +11,20 @@ type any interface{}
// TODO(rFindley) the below partially applied function types should probably // TODO(rFindley) the below partially applied function types should probably
// not be permitted (spec question). // not be permitted (spec question).
func f0[A any, B interface{~C}, C interface{~D}, D interface{~A}](A, B, C, D) // Embedding stand-alone type parameters is not permitted for now. Disabled.
func _() { // func f0[A any, B interface{~C}, C interface{~D}, D interface{~A}](A, B, C, D)
f := f0[string] // func _() {
f("a", "b", "c", "d") // f := f0[string]
f0("a", "b", "c", "d") // f("a", "b", "c", "d")
} // f0("a", "b", "c", "d")
// }
func f1[A any, B interface{~A}](A, B) //
func _() { // func f1[A any, B interface{~A}](A, B)
f := f1[int] // func _() {
f(int(0), int(0)) // f := f1[int]
f1(int(0), int(0)) // f(int(0), int(0))
} // f1(int(0), int(0))
// }
func f2[A any, B interface{~[]A}](A, B) func f2[A any, B interface{~[]A}](A, B)
func _() { func _() {
@ -32,13 +33,14 @@ func _() {
f2(byte(0), []byte{}) f2(byte(0), []byte{})
} }
func f3[A any, B interface{~C}, C interface{~*A}](A, B, C) // Embedding stand-alone type parameters is not permitted for now. Disabled.
func _() { // func f3[A any, B interface{~C}, C interface{~*A}](A, B, C)
f := f3[int] // func _() {
var x int // f := f3[int]
f(x, &x, &x) // var x int
f3(x, &x, &x) // f(x, &x, &x)
} // f3(x, &x, &x)
// }
func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C)
func _() { func _() {

View file

@ -31,9 +31,10 @@ type x7[A any] struct{ foo7 }
func main7() { var _ foo7 = x7[int]{} } func main7() { var _ foo7 = x7[int]{} }
// crash 8 // crash 8
type foo8[A any] interface { ~A } // Embedding stand-alone type parameters is not permitted for now. Disabled.
func bar8[A foo8[A]](a A) {} // type foo8[A any] interface { ~A }
func main8() {} // func bar8[A foo8[A]](a A) {}
// func main8() {}
// crash 9 // crash 9
type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] } type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] }

View file

@ -4,6 +4,9 @@
package p package p
// Embedding stand-alone type parameters is not permitted for now. Disabled.
/*
import "fmt" import "fmt"
// Minimal test case. // Minimal test case.
@ -25,3 +28,4 @@ func Print[T constr[T]](s []T) {
func f() { func f() {
Print([]string{"Hello, ", "playground\n"}) Print([]string{"Hello, ", "playground\n"})
} }
*/

View file

@ -2,14 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// TODO(rfindley) Eventually, once we disallow type lists, we need to package p
// adjust this code: for 1.17 we don't accept type parameters,
// and for 1.18 this code is valid.
// Leaving for now so we can see that existing errors
// are being reported.
package go1_17 // don't permit non-interface elements in interfaces
type T[P any] interface{ type T[P any] interface{
P // ERROR P is a type parameter, not an interface P // ERROR cannot embed a type parameter
} }

View file

@ -0,0 +1,37 @@
// Copyright 2021 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.
// Embedding of stand-alone type parameters is not permitted.
package p
type (
_[P any] interface{ *P | []P | chan P | map[string]P }
_[P any] interface{ P /* ERROR "cannot embed a type parameter" */ }
_[P any] interface{ ~P /* ERROR "cannot embed a type parameter" */ }
_[P any] interface{ int | P /* ERROR "cannot embed a type parameter" */ }
_[P any] interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }
)
func _[P any]() {
type (
_[P any] interface{ *P | []P | chan P | map[string]P }
_[P any] interface{ P /* ERROR "cannot embed a type parameter" */ }
_[P any] interface{ ~P /* ERROR "cannot embed a type parameter" */ }
_[P any] interface{ int | P /* ERROR "cannot embed a type parameter" */ }
_[P any] interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }
_ interface{ *P | []P | chan P | map[string]P }
_ interface{ P /* ERROR "cannot embed a type parameter" */ }
_ interface{ ~P /* ERROR "cannot embed a type parameter" */ }
_ interface{ int | P /* ERROR "cannot embed a type parameter" */ }
_ interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }
)
}
func _[P any, Q interface{ *P | []P | chan P | map[string]P }]()
func _[P any, Q interface{ P /* ERROR "cannot embed a type parameter" */ }]()
func _[P any, Q interface{ ~P /* ERROR "cannot embed a type parameter" */ }]()
func _[P any, Q interface{ int | P /* ERROR "cannot embed a type parameter" */ }]()
func _[P any, Q interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }]()

View file

@ -217,11 +217,9 @@ func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet {
// interface before go1.18. // interface before go1.18.
types = typ types = typ
case *TypeParam: case *TypeParam:
if check != nil && !check.allowVersion(check.pkg, 1, 18) { // Embedding stand-alone type parameters is not permitted for now.
check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is a type parameter, not an interface", typ) // This case is handled during union parsing.
continue unreachable()
}
types = typ
default: default:
if typ == Typ[Invalid] { if typ == Typ[Invalid] {
continue continue

View file

@ -131,13 +131,18 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type {
return newUnion(types, tilde) return newUnion(types, tilde)
} }
func parseTilde(check *Checker, x ast.Expr) (Type, bool) { func parseTilde(check *Checker, x ast.Expr) (typ Type, tilde bool) {
tilde := false
if op, _ := x.(*ast.UnaryExpr); op != nil && op.Op == token.TILDE { if op, _ := x.(*ast.UnaryExpr); op != nil && op.Op == token.TILDE {
x = op.X x = op.X
tilde = true tilde = true
} }
return check.anyType(x), tilde typ = check.anyType(x)
// embedding stand-alone type parameters is not permitted (issue #47127).
if _, ok := under(typ).(*TypeParam); ok {
check.error(x, _Todo, "cannot embed a type parameter")
typ = Typ[Invalid]
}
return
} }
// intersect computes the intersection of the types x and y, // intersect computes the intersection of the types x and y,