1
0
mirror of https://github.com/golang/go synced 2024-11-25 16:07:56 -07:00

cmd/compile: always write fun[0] in incomplete itab

runtime.getitab need filled fun[0] to identify whether
implemented the interface.

Fixes #51700
Fixes #52228

Change-Id: I0173b98f4e1b45e3a0183a5b60229d289140d1e6
Reviewed-on: https://go-review.googlesource.com/c/go/+/399058
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Auto-Submit: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Wayne Zuo 2022-04-08 23:44:40 +08:00 committed by Keith Randall
parent 5bf6c97e76
commit 6f5590edf6
3 changed files with 64 additions and 8 deletions

View File

@ -1328,21 +1328,21 @@ func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) {
// type itab struct {
// inter *interfacetype
// _type *_type
// hash uint32
// hash uint32 // copy of _type.hash. Used for type switches.
// _ [4]byte
// fun [1]uintptr // variable sized
// fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
// }
o := objw.SymPtr(lsym, 0, writeType(iface), 0)
o = objw.SymPtr(lsym, o, writeType(typ), 0)
o = objw.Uint32(lsym, o, types.TypeHash(typ)) // copy of type hash
o += 4 // skip unused field
if !completeItab {
// If typ doesn't implement iface, make method entries be zero.
o = objw.Uintptr(lsym, o, 0)
entries = entries[:0]
}
for _, fn := range entries {
if !completeItab {
// If typ doesn't implement iface, make method entries be zero.
o = objw.Uintptr(lsym, o, 0)
} else {
o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method
}
o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method
}
// Nothing writes static itabs, so they are read only.
objw.Global(lsym, int32(o), int16(obj.DUPOK|obj.RODATA))

View File

@ -0,0 +1,26 @@
// run
// Copyright 2022 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 main
func f[B any](b B) {
if b1, ok := any(b).(interface{ m1() }); ok {
panic(1)
_ = b1.(B)
}
if b2, ok := any(b).(interface{ m2() }); ok {
panic(2)
_ = b2.(B)
}
}
type S struct{}
func (S) m3() {}
func main() {
f(S{})
}

View File

@ -0,0 +1,30 @@
// run
// Copyright 2022 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 main
type SomeInterface interface {
Whatever()
}
func X[T any]() T {
var m T
// for this example, this block should never run
if _, ok := any(m).(SomeInterface); ok {
var dst SomeInterface
_, _ = dst.(T)
return dst.(T)
}
return m
}
type holder struct{}
func main() {
X[holder]()
}