]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: make sure shapes have proper indexes for sub-instantiation
authorDan Scales <danscales@google.com>
Wed, 29 Sep 2021 04:14:17 +0000 (21:14 -0700)
committerDan Scales <danscales@google.com>
Wed, 29 Sep 2021 16:09:04 +0000 (16:09 +0000)
The computation for determining the shapes to use at the top of
getInstantation was not always creating shapes with the proper indexes.
If an instantiation is being called from another instantiated function,
we cannot just copy the shape types unchanged, because their indexes may
have changed. So, for type args that already shapes, we still call
Shapify() with the correct index.

Fixes #48645

Change-Id: Ibb61c6f9a3c317220fb85135ca87eb5ad4dcff9e
Reviewed-on: https://go-review.googlesource.com/c/go/+/353030
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/noder/stencil.go
test/typeparam/issue48645a.go [new file with mode: 0644]
test/typeparam/issue48645a.out [new file with mode: 0644]
test/typeparam/issue48645b.go [new file with mode: 0644]

index e49702c04cb47f3d4e3340c611ab6f5368ea589d..2bc1756b8d8d8e120264b0c99f2b9fbf96718579 100644 (file)
@@ -610,21 +610,16 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth
        // number of instantiations we have to generate. You can actually have a mix
        // of shape and non-shape arguments, because of inferred or explicitly
        // specified concrete type args.
-       var s1 []*types.Type
+       s1 := make([]*types.Type, len(shapes))
        for i, t := range shapes {
                if !t.IsShape() {
-                       if s1 == nil {
-                               s1 = make([]*types.Type, len(shapes))
-                               copy(s1[0:i], shapes[0:i])
-                       }
                        s1[i] = typecheck.Shapify(t, i)
-               } else if s1 != nil {
-                       s1[i] = shapes[i]
+               } else {
+                       // Already a shape, but make sure it has the correct index.
+                       s1[i] = typecheck.Shapify(shapes[i].Underlying(), i)
                }
        }
-       if s1 != nil {
-               shapes = s1
-       }
+       shapes = s1
 
        sym := typecheck.MakeFuncInstSym(nameNode.Sym(), shapes, false, isMeth)
        info := g.instInfoMap[sym]
diff --git a/test/typeparam/issue48645a.go b/test/typeparam/issue48645a.go
new file mode 100644 (file)
index 0000000..8d5aac9
--- /dev/null
@@ -0,0 +1,31 @@
+// run -gcflags=-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 main
+
+import (
+       "fmt"
+       "reflect"
+)
+
+type Stream[T any] struct {
+}
+
+func (s Stream[T]) DropWhile() Stream[T] {
+       return Pipe[T, T](s)
+}
+
+func Pipe[T, R any](s Stream[T]) Stream[R] {
+       it := func(fn func(R) bool) {
+       }
+       fmt.Println(reflect.TypeOf(it).String())
+       return Stream[R]{}
+}
+
+func main() {
+       s := Stream[int]{}
+       s = s.DropWhile()
+}
diff --git a/test/typeparam/issue48645a.out b/test/typeparam/issue48645a.out
new file mode 100644 (file)
index 0000000..5093d0f
--- /dev/null
@@ -0,0 +1 @@
+func(func(int) bool)
diff --git a/test/typeparam/issue48645b.go b/test/typeparam/issue48645b.go
new file mode 100644 (file)
index 0000000..0f3a7f2
--- /dev/null
@@ -0,0 +1,81 @@
+// run -gcflags=-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 main
+
+type Iterator[T any] interface {
+       Iterate(fn func(T) bool)
+}
+
+type IteratorFunc[T any] func(fn func(T) bool)
+
+func (f IteratorFunc[T]) Iterate(fn func(T) bool) {
+       f(fn)
+}
+
+type Stream[T any] struct {
+       it Iterator[T]
+}
+
+func (s Stream[T]) Iterate(fn func(T) bool) {
+       if s.it == nil {
+               return
+       }
+       s.it.Iterate(fn)
+}
+
+func FromIterator[T any](it Iterator[T]) Stream[T] {
+       return Stream[T]{it: it}
+}
+
+func (s Stream[T]) DropWhile(fn func(T) bool) Stream[T] {
+       return Pipe[T, T](s, func(t T) (T, bool) {
+               return t, true
+       })
+}
+
+func Pipe[T, R any](s Stream[T], op func(d T) (R, bool)) Stream[R] {
+       it := func(fn func(R) bool) {
+               // XXX Not getting the closure right when converting to interface.
+               // s.it.Iterate(func(t T) bool {
+               //      r, ok := op(t)
+               //      if !ok {
+               //              return true
+               //      }
+
+               //      return fn(r)
+               // })
+       }
+
+       return FromIterator[R](IteratorFunc[R](it))
+}
+
+func Reduce[T, U any](s Stream[T], identity U, acc func(U, T) U) (r U) {
+       r = identity
+       s.Iterate(func(t T) bool {
+               r = acc(r, t)
+               return true
+       })
+
+       return r
+}
+
+type myIterator struct {
+}
+
+func (myIterator) Iterate(fn func(int) bool) {
+}
+
+func main() {
+       s := Stream[int]{}
+       s.it = myIterator{}
+       s = s.DropWhile(func(i int) bool {
+               return false
+       })
+       Reduce(s, nil, func(acc []int, e int) []int {
+               return append(acc, e)
+       })
+}