cmd/compile/internal/types2: do not declare new methods on instantiated types

Report an error if an alias is used to declare a method on an
instantiated type.

Also, when resolving the receiver type, don't use asNamed to
avoid premature expansion of the type.

Fixes #47968.

Change-Id: Ie5acc4cfb1944deaaeeaee98707f31e256f8ef5e
Reviewed-on: https://go-review.googlesource.com/c/go/+/345472
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Robert Griesemer 2021-08-26 12:27:06 -07:00
parent 03db2c2413
commit af80af22b5
2 changed files with 28 additions and 1 deletions

View file

@ -132,7 +132,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
// Also: Don't report an error via genericType since it will be reported
// again when we type-check the signature.
// TODO(gri) maybe the receiver should be marked as invalid instead?
if recv := asNamed(check.genericType(rname, false)); recv != nil {
if recv, _ := check.genericType(rname, false).(*Named); recv != nil {
recvTParams = recv.TParams().list()
}
}
@ -211,6 +211,12 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
switch T := rtyp.(type) {
case *Named:
T.expand(nil)
// The receiver type may be an instantiated type referred to
// by an alias (which cannot have receiver parameters for now).
if T.TArgs() != nil && sig.RParams() == nil {
check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ)
break
}
// spec: "The type denoted by T is called the receiver base type; it must not
// be a pointer or interface type and it must be declared in the same package
// as the method."

View file

@ -0,0 +1,21 @@
// 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
type T[P any] struct{}
func (T[P]) m1()
type A1 = T
func (A1[P]) m2() {}
type A2 = T[int]
func (A2 /* ERROR cannot define methods on instantiated type T\[int\] */) m3() {}
func (_ /* ERROR cannot define methods on instantiated type T\[int\] */ A2) m4() {}
func (T[int]) m5() {} // int is the type parameter name, not an instantiation
func (T[* /* ERROR must be an identifier */ int]) m6() {} // syntax error