go/types, types2: better error message for invalid type parameter term

The spec says "In a union, a term cannot be a type parameter,...",
but it's really the type in a term that cannot be a type parameter.
(Also, for the spec's purposes, a single term is still a union.)

This CL changes the current error message from:

        "cannot use type parameter in typeset"

to one of two messages:

        "term cannot be a type parameter"           (for term of form P)
        "type in term ~P cannot be a type parameter (for term of form ~P)

which are more specific and match the spec more closely.

Fixes #50420.

Change-Id: Id48503efc8416cabc03d5c40d8e64d5b3a7f078e
Reviewed-on: https://go-review.googlesource.com/c/go/+/396874
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Robert Griesemer 2022-03-30 12:19:24 -07:00
parent 109a18dce7
commit 2ea9376266
8 changed files with 50 additions and 42 deletions

View File

@ -44,9 +44,9 @@ type (
type (
_[T interface{ *T } ] struct{} // ok
_[T interface{ int | *T } ] struct{} // ok
_[T interface{ T /* ERROR cannot embed a type parameter */ } ] struct{}
_[T interface{ ~T /* ERROR cannot embed a type parameter */ } ] struct{}
_[T interface{ int|T /* ERROR cannot embed a type parameter */ }] struct{}
_[T interface{ T /* ERROR term cannot be a type parameter */ } ] struct{}
_[T interface{ ~T /* ERROR type in term ~T cannot be a type parameter */ } ] struct{}
_[T interface{ int|T /* ERROR term cannot be a type parameter */ }] struct{}
)
// Multiple embedded union elements are intersected. The order in which they

View File

@ -5,5 +5,5 @@
package p
type T[P any] interface{
P // ERROR cannot embed a type parameter
P // ERROR term cannot be a type parameter
}

View File

@ -8,30 +8,30 @@ 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" */ }
_[P any] interface{ P /* ERROR term cannot be a type parameter */ }
_[P any] interface{ ~P /* ERROR type in term ~P cannot be a type parameter */ }
_[P any] interface{ int | P /* ERROR term cannot be a type parameter */ }
_[P any] interface{ int | ~P /* ERROR type in term ~P cannot be 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" */ }
_[P any] interface{ P /* ERROR term cannot be a type parameter */ }
_[P any] interface{ ~P /* ERROR type in term ~P cannot be a type parameter */ }
_[P any] interface{ int | P /* ERROR term cannot be a type parameter */ }
_[P any] interface{ int | ~P /* ERROR type in term ~P cannot be 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" */ }
_ interface{ P /* ERROR term cannot be a type parameter */ }
_ interface{ ~P /* ERROR type in term ~P cannot be a type parameter */ }
_ interface{ int | P /* ERROR term cannot be a type parameter */ }
_ interface{ int | ~P /* ERROR type in term ~P cannot be 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" */ }]() {}
func _[P any, Q interface{ P /* ERROR term cannot be a type parameter */ }]() {}
func _[P any, Q interface{ ~P /* ERROR type in term ~P cannot be a type parameter */ }]() {}
func _[P any, Q interface{ int | P /* ERROR term cannot be a type parameter */ }]() {}
func _[P any, Q interface{ int | ~P /* ERROR type in term ~P cannot be a type parameter */ }]() {}

View File

@ -148,7 +148,11 @@ func parseTilde(check *Checker, tx syntax.Expr) *Term {
// simply use its underlying type (like we do for other named, embedded interfaces),
// and since the underlying type is an interface the embedding is well defined.
if isTypeParam(typ) {
check.error(x, "cannot embed a type parameter")
if tilde {
check.errorf(x, "type in term %s cannot be a type parameter", tx)
} else {
check.error(x, "term cannot be a type parameter")
}
typ = Typ[Invalid]
}
term := NewTerm(tilde, typ)

View File

@ -44,9 +44,9 @@ type (
type (
_[T interface{ *T } ] struct{} // ok
_[T interface{ int | *T } ] struct{} // ok
_[T interface{ T /* ERROR cannot embed a type parameter */ } ] struct{}
_[T interface{ ~T /* ERROR cannot embed a type parameter */ } ] struct{}
_[T interface{ int|T /* ERROR cannot embed a type parameter */ }] struct{}
_[T interface{ T /* ERROR term cannot be a type parameter */ } ] struct{}
_[T interface{ ~T /* ERROR type in term ~T cannot be a type parameter */ } ] struct{}
_[T interface{ int|T /* ERROR term cannot be a type parameter */ }] struct{}
)
// Multiple embedded union elements are intersected. The order in which they

View File

@ -5,5 +5,5 @@
package p
type T[P any] interface{
P // ERROR cannot embed a type parameter
P // ERROR term cannot be a type parameter
}

View File

@ -8,30 +8,30 @@ 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" */ }
_[P any] interface{ P /* ERROR term cannot be a type parameter */ }
_[P any] interface{ ~P /* ERROR type in term ~P cannot be a type parameter */ }
_[P any] interface{ int | P /* ERROR term cannot be a type parameter */ }
_[P any] interface{ int | ~P /* ERROR type in term ~P cannot be 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" */ }
_[P any] interface{ P /* ERROR term cannot be a type parameter */ }
_[P any] interface{ ~P /* ERROR type in term ~P cannot be a type parameter */ }
_[P any] interface{ int | P /* ERROR term cannot be a type parameter */ }
_[P any] interface{ int | ~P /* ERROR type in term ~P cannot be 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" */ }
_ interface{ P /* ERROR term cannot be a type parameter */ }
_ interface{ ~P /* ERROR type in term ~P cannot be a type parameter */ }
_ interface{ int | P /* ERROR term cannot be a type parameter */ }
_ interface{ int | ~P /* ERROR type in term ~P cannot be 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" */ }]() {}
func _[P any, Q interface{ P /* ERROR term cannot be a type parameter */ }]() {}
func _[P any, Q interface{ ~P /* ERROR type in term ~P cannot be a type parameter */ }]() {}
func _[P any, Q interface{ int | P /* ERROR term cannot be a type parameter */ }]() {}
func _[P any, Q interface{ int | ~P /* ERROR type in term ~P cannot be a type parameter */ }]() {}

View File

@ -151,7 +151,11 @@ func parseTilde(check *Checker, tx ast.Expr) *Term {
// simply use its underlying type (like we do for other named, embedded interfaces),
// and since the underlying type is an interface the embedding is well defined.
if isTypeParam(typ) {
check.error(x, _MisplacedTypeParam, "cannot embed a type parameter")
if tilde {
check.errorf(x, _MisplacedTypeParam, "type in term %s cannot be a type parameter", tx)
} else {
check.error(x, _MisplacedTypeParam, "term cannot be a type parameter")
}
typ = Typ[Invalid]
}
term := NewTerm(tilde, typ)