]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, cmd/compile: fix composite literal structural typing
authorMatthew Dempsky <mdempsky@google.com>
Wed, 26 Jan 2022 21:46:45 +0000 (13:46 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 27 Jan 2022 19:55:38 +0000 (19:55 +0000)
For a composite literal expression like []T{{f: 1}}, we allow T to be
a pointer to struct type, so it's consistent to allow T to also be a
type parameter whose structural type is a pointer to struct type.

Fixes #50833.

Change-Id: Ib0781ec4a4f327c875ea25b97740ff2c0c86b916
Reviewed-on: https://go-review.googlesource.com/c/go/+/381075
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/compile/internal/noder/expr.go
src/cmd/compile/internal/noder/writer.go
src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/testdata/fixedbugs/issue50833.go2 [new file with mode: 0644]
src/go/types/expr.go
src/go/types/testdata/fixedbugs/issue50833.go2 [new file with mode: 0644]
test/typeparam/issue50833.go [new file with mode: 0644]

index 6891d1ec30dac2244a87ebe494ace67058b2f611..8a9afeb0959c533880a25c91b1cd0448d3186eb8 100644 (file)
@@ -332,7 +332,7 @@ func (g *irgen) exprs(exprs []syntax.Expr) []ir.Node {
 }
 
 func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node {
-       if ptr, ok := typ.Underlying().(*types2.Pointer); ok {
+       if ptr, ok := types2.StructuralType(typ).(*types2.Pointer); ok {
                n := ir.NewAddrExpr(g.pos(lit), g.compLit(ptr.Elem(), lit))
                n.SetOp(ir.OPTRLIT)
                return typed(g.typ(typ), n)
index 73f2df8e39a508cde2938e4cdf303a4fd78ec131..933f5778253a914a4f3552d234abc8d35ade8168 100644 (file)
@@ -1338,8 +1338,7 @@ func (w *writer) compLit(lit *syntax.CompositeLit) {
        w.typ(tv.Type)
 
        typ := tv.Type
-       // TODO(mdempsky): Use types2.StructuralType here too? See #50833.
-       if ptr, ok := typ.Underlying().(*types2.Pointer); ok {
+       if ptr, ok := types2.StructuralType(typ).(*types2.Pointer); ok {
                typ = ptr.Elem()
        }
        str, isStruct := types2.StructuralType(typ).(*types2.Struct)
index 3d6d9153eeb88969fce40a4fbf020cf0bfc62d5a..7a668d20f18cdd52e840fec4d00ea4d51b63108b 100644 (file)
@@ -1262,11 +1262,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
                case hint != nil:
                        // no composite literal type present - use hint (element type of enclosing type)
                        typ = hint
-                       base = typ
-                       if !isTypeParam(typ) {
-                               base = under(typ)
-                       }
-                       base, _ = deref(base) // *T implies &T{}
+                       base, _ = deref(structuralType(typ)) // *T implies &T{}
 
                default:
                        // TODO(gri) provide better error messages depending on context
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50833.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50833.go2
new file mode 100644 (file)
index 0000000..e912e4d
--- /dev/null
@@ -0,0 +1,16 @@
+// 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 p
+
+type (
+       S  struct{ f int }
+       PS *S
+)
+
+func a() []*S { return []*S{{f: 1}} }
+func b() []PS { return []PS{{f: 1}} }
+
+func c[P *S]() []P { return []P{{f: 1}} }
+func d[P PS]() []P { return []P{{f: 1}} }
index 36f0f467be142c63e214850d4cd2f88e76ed4d79..44e0288d3e9dfb937ee094a14805918822c603dd 100644 (file)
@@ -1241,11 +1241,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                case hint != nil:
                        // no composite literal type present - use hint (element type of enclosing type)
                        typ = hint
-                       base = typ
-                       if !isTypeParam(typ) {
-                               base = under(typ)
-                       }
-                       base, _ = deref(base) // *T implies &T{}
+                       base, _ = deref(structuralType(typ)) // *T implies &T{}
 
                default:
                        // TODO(gri) provide better error messages depending on context
diff --git a/src/go/types/testdata/fixedbugs/issue50833.go2 b/src/go/types/testdata/fixedbugs/issue50833.go2
new file mode 100644 (file)
index 0000000..e912e4d
--- /dev/null
@@ -0,0 +1,16 @@
+// 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 p
+
+type (
+       S  struct{ f int }
+       PS *S
+)
+
+func a() []*S { return []*S{{f: 1}} }
+func b() []PS { return []PS{{f: 1}} }
+
+func c[P *S]() []P { return []P{{f: 1}} }
+func d[P PS]() []P { return []P{{f: 1}} }
diff --git a/test/typeparam/issue50833.go b/test/typeparam/issue50833.go
new file mode 100644 (file)
index 0000000..07c1a86
--- /dev/null
@@ -0,0 +1,23 @@
+// 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 (
+       S  struct{ f int }
+       PS *S
+)
+
+func a() []*S { return []*S{{f: 1}} }
+func b() []PS { return []PS{{f: 1}} }
+
+func c[P *S]() []P { return []P{{f: 1}} }
+func d[P PS]() []P { return []P{{f: 1}} }
+
+func main() {
+       c[*S]()
+       d[PS]()
+}