]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: mark type descriptors as always dupok
authorKeith Randall <khr@golang.org>
Sat, 30 Oct 2021 21:39:29 +0000 (14:39 -0700)
committerKeith Randall <khr@golang.org>
Tue, 2 Nov 2021 18:31:53 +0000 (18:31 +0000)
The types of the two interfaces should be equal, but they aren't.
We end up with multiple descriptors for a type when we need type
descriptors to be unique.

Fixes #49241

Change-Id: I8a6c70da541c6088a92a01392bc83b61cc130eba
Reviewed-on: https://go-review.googlesource.com/c/go/+/360134
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/reflectdata/reflect.go
test/typeparam/issue49241.dir/a.go [new file with mode: 0644]
test/typeparam/issue49241.dir/b.go [new file with mode: 0644]
test/typeparam/issue49241.dir/c.go [new file with mode: 0644]
test/typeparam/issue49241.dir/main.go [new file with mode: 0644]
test/typeparam/issue49241.go [new file with mode: 0644]

index ce41b8c9344a1dcee8d800e93c9123a732f47f0d..d396c249e49869fe382a63aa12d4cfe1cb5a6fe1 100644 (file)
@@ -959,11 +959,6 @@ func writeType(t *types.Type) *obj.LSym {
                base.Fatalf("unresolved defined type: %v", tbase)
        }
 
-       dupok := 0
-       if tbase.Sym() == nil || tbase.HasShape() { // TODO(mdempsky): Probably need DUPOK for instantiated types too.
-               dupok = obj.DUPOK
-       }
-
        if !NeedEmit(tbase) {
                if i := typecheck.BaseTypeIndex(t); i >= 0 {
                        lsym.Pkg = tbase.Sym().Pkg.Prefix
@@ -1196,7 +1191,9 @@ func writeType(t *types.Type) *obj.LSym {
        }
 
        ot = dextratypeData(lsym, ot, t)
-       objw.Global(lsym, int32(ot), int16(dupok|obj.RODATA))
+       objw.Global(lsym, int32(ot), int16(obj.DUPOK|obj.RODATA))
+       // Note: DUPOK is required to ensure that we don't end up with more
+       // than one type descriptor for a given type.
 
        // The linker will leave a table of all the typelinks for
        // types in the binary, so the runtime can find them.
diff --git a/test/typeparam/issue49241.dir/a.go b/test/typeparam/issue49241.dir/a.go
new file mode 100644 (file)
index 0000000..34c9965
--- /dev/null
@@ -0,0 +1,13 @@
+// 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 a
+
+type T[P any] struct {
+       x P
+}
+
+type U struct {
+       a,b int
+}
diff --git a/test/typeparam/issue49241.dir/b.go b/test/typeparam/issue49241.dir/b.go
new file mode 100644 (file)
index 0000000..45c1afb
--- /dev/null
@@ -0,0 +1,17 @@
+// 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 b
+
+import "a"
+
+//go:noinline
+func F() interface {} {
+       return a.T[int]{}
+}
+
+//go:noinline
+func G() interface{} {
+       return struct{X,Y a.U}{}
+}
diff --git a/test/typeparam/issue49241.dir/c.go b/test/typeparam/issue49241.dir/c.go
new file mode 100644 (file)
index 0000000..ea3bab2
--- /dev/null
@@ -0,0 +1,17 @@
+// 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 c
+
+import "a"
+
+//go:noinline
+func F() interface {} {
+       return a.T[int]{}
+}
+
+//go:noinline
+func G() interface{} {
+       return struct{X,Y a.U}{}
+}
diff --git a/test/typeparam/issue49241.dir/main.go b/test/typeparam/issue49241.dir/main.go
new file mode 100644 (file)
index 0000000..7c8a8b1
--- /dev/null
@@ -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 main
+
+import (
+       "b"
+       "c"
+)
+
+func main() {
+       if b.G() != c.G() {
+               println(b.G(), c.G())
+               panic("bad")
+       }
+       if b.F() != c.F() {
+               println(b.F(), c.F())
+               panic("bad")
+       }
+}
diff --git a/test/typeparam/issue49241.go b/test/typeparam/issue49241.go
new file mode 100644 (file)
index 0000000..76930e5
--- /dev/null
@@ -0,0 +1,7 @@
+// rundir -G=3
+
+// 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 ignored