]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.18] cmd/compile: always write fun[0] in incomplete itab
authorKeith Randall <khr@golang.org>
Fri, 8 Apr 2022 15:44:40 +0000 (23:44 +0800)
committerHeschi Kreinick <heschi@google.com>
Mon, 9 May 2022 20:25:20 +0000 (20:25 +0000)
runtime.getitab need filled fun[0] to identify whether
implemented the interface.

Fixes #51738
Fixes #52244

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>
Reviewed-on: https://go-review.googlesource.com/c/go/+/399974
Reviewed-by: Austin Clements <austin@google.com>
src/cmd/compile/internal/reflectdata/reflect.go
test/typeparam/issue51700.go [new file with mode: 0644]
test/typeparam/issue52228.go [new file with mode: 0644]

index 822a1dacc354c63b8bbf5a4e174a6a4bc98476fd..aec7358c32263b37a0845c06bc599833156b5b78 100644 (file)
@@ -1321,21 +1321,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))
diff --git a/test/typeparam/issue51700.go b/test/typeparam/issue51700.go
new file mode 100644 (file)
index 0000000..e253157
--- /dev/null
@@ -0,0 +1,26 @@
+// run -gcflags=-G=3
+
+// 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{})
+}
diff --git a/test/typeparam/issue52228.go b/test/typeparam/issue52228.go
new file mode 100644 (file)
index 0000000..f065c8e
--- /dev/null
@@ -0,0 +1,30 @@
+// run -gcflags=-G=3
+
+// 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]()
+}