From 57c8d7fe0a1e3f1b5c2643754ea433fa394f6713 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 4 Dec 2019 14:21:58 -0800 Subject: [PATCH] go/types: do not permit parenthesized uninstantiated generic types Document the design decision. Change-Id: Ied5d77bc576653b49edcde4cdb3f6b95623a9045 --- src/go/types/NOTES | 8 +++++++- src/go/types/contracts.go | 2 +- src/go/types/examples/types.go2 | 9 +++++---- src/go/types/typexpr.go | 3 ++- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/go/types/NOTES b/src/go/types/NOTES index 8613b12fac..1d300a3ef2 100644 --- a/src/go/types/NOTES +++ b/src/go/types/NOTES @@ -7,4 +7,10 @@ TODO (need an allTypes list, like we have an allMethods list?) OPEN ISSUES -- do we allow parenthesized generic uninstantiated types? + +DESIGN DECISIONS +- 12/4/2019: do not allow parenthesized generic uninstantiated types (unless instantiated implicitly) + In other words: generic types must always be instantiated before they can be used in any form + More generally: Only permit type instantiation T(x) in type context, when the type is a named type. + Do not permit in in general in type context: e.g., disallow []T(x) because we consider that a + conversion, in general. Same for ([]T)(x). diff --git a/src/go/types/contracts.go b/src/go/types/contracts.go index c5bc9d381c..20d5d7e59d 100644 --- a/src/go/types/contracts.go +++ b/src/go/types/contracts.go @@ -249,7 +249,7 @@ func (check *Checker) satisfyContract(contr *Contract, targs []Type) bool { for i, targ := range targs { iface := contr.ifaceAt(i) - // If iface is parameterized, we need to replace the type parameters + // If iface is generic, we need to replace the type parameters // with the respective type arguments. // TODO(gri) fix this if IsParameterized(iface) { diff --git a/src/go/types/examples/types.go2 b/src/go/types/examples/types.go2 index 2172c9f346..db70cfe0a1 100644 --- a/src/go/types/examples/types.go2 +++ b/src/go/types/examples/types.go2 @@ -83,7 +83,7 @@ func _() { x1a.f = x2a.f } -// Another interesting corner case is parameterized types that don't use +// Another interesting corner case are generic types that don't use // their type arguments. For instance: type T(type P) struct{} @@ -101,8 +101,9 @@ func _() { xint = xbool // ERROR assignment } -// Parameterized types cannot be used without instantiation. +// Generic types cannot be used without instantiation. var _ T // ERROR cannot use generic type T -// TODO(gri) Should we allow parentheses around generic, uninstantiated types? -// var _ (T)(int) +// In type context, parameterized (generic) types cannot use instantiation syntax. +// See also NOTES entry from 12/4/2019. +var _ (T /* ERROR cannot use generic type T */ )( /* ERROR expected ';' */ int) diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 174f74594f..f33db38fce 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -321,7 +321,8 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) (T Type) { return typ case *ast.ParenExpr: - // TODO(gri) should we allow parenthesized generic (uninstantiated) types? + // Generic types must be instantiated before they can be used in any form. + // Consequently, generic types cannot be parenthesized. return check.definedType(e.X, def) case *ast.ArrayType: