mirror of
https://github.com/golang/go
synced 2024-11-17 12:04:43 -07:00
[dev.typeparams] go/types: disallow "free" type parameter as RHS of a type declaration
This is a port of CL 332411 to go/types. methodset_test.go is similarly updated. Change-Id: I332b1837a954acc9d3b7e0e2ad2bec3425f088f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/335109 Reviewed-by: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
521828091c
commit
c4cd76fbbb
@ -680,18 +680,18 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
|
|||||||
alias = false
|
alias = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// alias declaration
|
||||||
if alias {
|
if alias {
|
||||||
// type alias declaration
|
|
||||||
if !check.allowVersion(check.pkg, 1, 9) {
|
if !check.allowVersion(check.pkg, 1, 9) {
|
||||||
check.errorf(atPos(tdecl.Assign), _BadDecl, "type aliases requires go1.9 or later")
|
check.errorf(atPos(tdecl.Assign), _BadDecl, "type aliases requires go1.9 or later")
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.typ = Typ[Invalid]
|
obj.typ = Typ[Invalid]
|
||||||
obj.typ = check.anyType(tdecl.Type)
|
obj.typ = check.anyType(tdecl.Type)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
// type definition or generic type declaration
|
||||||
// defined type declaration
|
|
||||||
|
|
||||||
named := check.newNamed(obj, nil, nil, nil, nil)
|
named := check.newNamed(obj, nil, nil, nil, nil)
|
||||||
def.setUnderlying(named)
|
def.setUnderlying(named)
|
||||||
|
|
||||||
@ -720,8 +720,12 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
|
|||||||
// TODO(gri) Investigate if we can just use named.fromRHS here
|
// TODO(gri) Investigate if we can just use named.fromRHS here
|
||||||
// and rely on lazy computation of the underlying type.
|
// and rely on lazy computation of the underlying type.
|
||||||
named.underlying = under(named)
|
named.underlying = under(named)
|
||||||
}
|
|
||||||
|
|
||||||
|
// If the RHS is a type parameter, it must be from this type declaration.
|
||||||
|
if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.tparams, tpar) < 0 {
|
||||||
|
check.errorf(tdecl.Type, _Todo, "cannot use function type parameter %s as RHS in type declaration", tpar)
|
||||||
|
named.underlying = Typ[Invalid]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (check *Checker) collectTypeParams(list *ast.FieldList) []*TypeName {
|
func (check *Checker) collectTypeParams(list *ast.FieldList) []*TypeName {
|
||||||
|
@ -50,8 +50,9 @@ func TestNewMethodSet(t *testing.T) {
|
|||||||
"type C interface{ f() }; func g[T C]() { var a T; _ = a }": {{"f", []int{0}, true}},
|
"type C interface{ f() }; func g[T C]() { var a T; _ = a }": {{"f", []int{0}, true}},
|
||||||
"type C interface{ f() }; func g[T C]() { var a struct{T}; _ = a }": {{"f", []int{0, 0}, true}},
|
"type C interface{ f() }; func g[T C]() { var a struct{T}; _ = a }": {{"f", []int{0, 0}, true}},
|
||||||
|
|
||||||
// Issue #45639.
|
// Issue #45639: We don't allow this anymore. Keep this code in case we
|
||||||
"type C interface{ f() }; func g[T C]() { type Y T; var a Y; _ = a }": {},
|
// decide to revisit this decision.
|
||||||
|
// "type C interface{ f() }; func g[T C]() { type Y T; var a Y; _ = a }": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
check := func(src string, methods []method, generic bool) {
|
check := func(src string, methods []method, generic bool) {
|
||||||
|
48
src/go/types/testdata/examples/types.go2
vendored
48
src/go/types/testdata/examples/types.go2
vendored
@ -161,30 +161,40 @@ type _ struct {
|
|||||||
* /* ERROR List redeclared */ List[int]
|
* /* ERROR List redeclared */ List[int]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #45639: We don't allow this anymore. Keep this code
|
||||||
|
// in case we decide to revisit this decision.
|
||||||
|
//
|
||||||
// It's possible to declare local types whose underlying types
|
// It's possible to declare local types whose underlying types
|
||||||
// are type parameters. As with ordinary type definitions, the
|
// are type parameters. As with ordinary type definitions, the
|
||||||
// types underlying properties are "inherited" but the methods
|
// types underlying properties are "inherited" but the methods
|
||||||
// are not.
|
// are not.
|
||||||
func _[T interface{ m(); ~int }]() {
|
//func _[T interface{ m(); ~int }]() {
|
||||||
type L T
|
// type L T
|
||||||
var x L
|
// var x L
|
||||||
|
//
|
||||||
|
// // m is not defined on L (it is not "inherited" from
|
||||||
|
// // its underlying type).
|
||||||
|
// x.m /* ERROR x.m undefined */ ()
|
||||||
|
//
|
||||||
|
// // But the properties of T, such that as that it supports
|
||||||
|
// // the operations of the types given by its type bound,
|
||||||
|
// // are also the properties of L.
|
||||||
|
// x++
|
||||||
|
// _ = x - x
|
||||||
|
//
|
||||||
|
// // On the other hand, if we define a local alias for T,
|
||||||
|
// // that alias stands for T as expected.
|
||||||
|
// type A = T
|
||||||
|
// var y A
|
||||||
|
// y.m()
|
||||||
|
// _ = y < 0
|
||||||
|
//}
|
||||||
|
|
||||||
// m is not defined on L (it is not "inherited" from
|
// It is not permitted to declare a local type whose underlying
|
||||||
// its underlying type).
|
// type is a type parameters not declared by that type declaration.
|
||||||
x.m /* ERROR x.m undefined */ ()
|
func _[T any]() {
|
||||||
|
type _ T // ERROR cannot use function type parameter T as RHS in type declaration
|
||||||
// But the properties of T, such that as that it supports
|
type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration
|
||||||
// the operations of the types given by its type bound,
|
|
||||||
// are also the properties of L.
|
|
||||||
x++
|
|
||||||
_ = x - x
|
|
||||||
|
|
||||||
// On the other hand, if we define a local alias for T,
|
|
||||||
// that alias stands for T as expected.
|
|
||||||
type A = T
|
|
||||||
var y A
|
|
||||||
y.m()
|
|
||||||
_ = y < 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// As a special case, an explicit type argument may be omitted
|
// As a special case, an explicit type argument may be omitted
|
||||||
|
12
src/go/types/testdata/fixedbugs/issue45639.go2
vendored
Normal file
12
src/go/types/testdata/fixedbugs/issue45639.go2
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package P
|
||||||
|
|
||||||
|
// It is not permitted to declare a local type whose underlying
|
||||||
|
// type is a type parameters not declared by that type declaration.
|
||||||
|
func _[T any]() {
|
||||||
|
type _ T // ERROR cannot use function type parameter T as RHS in type declaration
|
||||||
|
type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration
|
||||||
|
}
|
@ -147,10 +147,17 @@ func (u *unifier) join(i, j int) bool {
|
|||||||
// If typ is a type parameter of d, index returns the type parameter index.
|
// If typ is a type parameter of d, index returns the type parameter index.
|
||||||
// Otherwise, the result is < 0.
|
// Otherwise, the result is < 0.
|
||||||
func (d *tparamsList) index(typ Type) int {
|
func (d *tparamsList) index(typ Type) int {
|
||||||
if t, ok := typ.(*TypeParam); ok {
|
if tpar, ok := typ.(*TypeParam); ok {
|
||||||
if i := t.index; i < len(d.tparams) && d.tparams[i].typ == t {
|
return tparamIndex(d.tparams, tpar)
|
||||||
return i
|
|
||||||
}
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// If tpar is a type parameter in list, tparamIndex returns the type parameter index.
|
||||||
|
// Otherwise, the result is < 0. tpar must not be nil.
|
||||||
|
func tparamIndex(list []*TypeName, tpar *TypeParam) int {
|
||||||
|
if i := tpar.index; i < len(list) && list[i].typ == tpar {
|
||||||
|
return i
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user