mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.typeparams] go/types: don't permit method calls on ptr to type parameter receivers
This is a port of CL 332609 to go/types. Change-Id: I3482ea1b97bc7101b987ef312cd6cade80a5843f Reviewed-on: https://go-review.googlesource.com/c/go/+/335112 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:
parent
9b85985d36
commit
76b39959f4
4 changed files with 36 additions and 16 deletions
|
|
@ -75,11 +75,13 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
|
||||||
|
|
||||||
typ, isPtr := deref(T)
|
typ, isPtr := deref(T)
|
||||||
|
|
||||||
// *typ where typ is an interface has no methods.
|
// *typ where typ is an interface or type parameter has no methods.
|
||||||
// Be cautious: typ may be nil (issue 39634, crash #3).
|
switch under(typ).(type) {
|
||||||
if typ == nil || isPtr && IsInterface(typ) {
|
case *Interface, *TypeParam:
|
||||||
|
if isPtr {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Start with typ as single entry at shallowest depth.
|
// Start with typ as single entry at shallowest depth.
|
||||||
current := []embeddedType{{typ, nil, isPtr, false}}
|
current := []embeddedType{{typ, nil, isPtr, false}}
|
||||||
|
|
|
||||||
10
src/go/types/testdata/check/issues.go2
vendored
10
src/go/types/testdata/check/issues.go2
vendored
|
|
@ -24,22 +24,20 @@ func _() {
|
||||||
eql[io.Reader](nil, nil)
|
eql[io.Reader](nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a receiver of pointer type (below: *T) we must ignore
|
// If we have a receiver of pointer to type parameter type (below: *T)
|
||||||
// the pointer in the implementation of the method lookup because
|
// we don't have any methods, like for interfaces.
|
||||||
// the type bound of T is an interface and pointer to interface types
|
|
||||||
// have no methods and then the lookup would fail.
|
|
||||||
type C[T any] interface {
|
type C[T any] interface {
|
||||||
m()
|
m()
|
||||||
}
|
}
|
||||||
|
|
||||||
// using type bound C
|
// using type bound C
|
||||||
func _[T C[T]](x *T) {
|
func _[T C[T]](x *T) {
|
||||||
x.m()
|
x.m /* ERROR x\.m undefined */ ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// using an interface literal as bound
|
// using an interface literal as bound
|
||||||
func _[T interface{ m() }](x *T) {
|
func _[T interface{ m() }](x *T) {
|
||||||
x.m()
|
x.m /* ERROR x\.m undefined */ ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// In a generic function body all method calls will be pointer method calls.
|
// In a generic function body all method calls will be pointer method calls.
|
||||||
|
|
|
||||||
20
src/go/types/testdata/fixedbugs/issue47031.go2
vendored
Normal file
20
src/go/types/testdata/fixedbugs/issue47031.go2
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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 Mer interface { M() }
|
||||||
|
|
||||||
|
func F[T Mer](p *T) {
|
||||||
|
p.M /* ERROR p\.M undefined */ ()
|
||||||
|
}
|
||||||
|
|
||||||
|
type MyMer int
|
||||||
|
|
||||||
|
func (MyMer) M() {}
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
F(new(MyMer))
|
||||||
|
F[Mer](nil)
|
||||||
|
}
|
||||||
|
|
@ -113,11 +113,6 @@ func asSignature(t Type) *Signature {
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
func asInterface(t Type) *Interface {
|
|
||||||
op, _ := optype(t).(*Interface)
|
|
||||||
return op
|
|
||||||
}
|
|
||||||
|
|
||||||
func asMap(t Type) *Map {
|
func asMap(t Type) *Map {
|
||||||
op, _ := optype(t).(*Map)
|
op, _ := optype(t).(*Map)
|
||||||
return op
|
return op
|
||||||
|
|
@ -128,10 +123,15 @@ func asChan(t Type) *Chan {
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the argument to asNamed and asTypeParam is of the respective types
|
// If the argument to asInterface, asNamed, or asTypeParam is of the respective type
|
||||||
// (possibly after expanding an instance type), these methods return that type.
|
// (possibly after expanding an instance type), these methods return that type.
|
||||||
// Otherwise the result is nil.
|
// Otherwise the result is nil.
|
||||||
|
|
||||||
|
func asInterface(t Type) *Interface {
|
||||||
|
op, _ := optype(t).(*Interface)
|
||||||
|
return op
|
||||||
|
}
|
||||||
|
|
||||||
func asNamed(t Type) *Named {
|
func asNamed(t Type) *Named {
|
||||||
e, _ := expand(t).(*Named)
|
e, _ := expand(t).(*Named)
|
||||||
return e
|
return e
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue