]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: export OFUNCINST and OSELRECV2 nodes (for generic funct...
authorDan Scales <danscales@google.com>
Sun, 9 May 2021 18:38:34 +0000 (11:38 -0700)
committerDan Scales <danscales@google.com>
Fri, 21 May 2021 17:03:30 +0000 (17:03 +0000)
Added new test typeparam/factimp.go and changed a bunch of other tests
to test exporting more generic functions and types.

Change-Id: I573d75431cc92482f8f908695cfbc8e84dbb36d2
Reviewed-on: https://go-review.googlesource.com/c/go/+/321749
Trust: Dan Scales <danscales@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/typecheck/iexport.go
src/cmd/compile/internal/typecheck/iimport.go
test/typeparam/combine.go
test/typeparam/cons.go
test/typeparam/factimp.dir/a.go [new file with mode: 0644]
test/typeparam/factimp.dir/main.go [new file with mode: 0644]
test/typeparam/factimp.go [new file with mode: 0644]
test/typeparam/index.go
test/typeparam/listimp.dir/a.go
test/typeparam/listimp.dir/main.go
test/typeparam/lockable.go

index e6813adbf90eb60005541f64b169493a7162ce89..d125dadd883d03802a3a34469ae8c054bd9f6b42 100644 (file)
@@ -1920,6 +1920,26 @@ func (w *exportWriter) expr(n ir.Node) {
                // if exporting, DCLCONST should just be removed as its usage
                // has already been replaced with literals
 
+       case ir.OFUNCINST:
+               n := n.(*ir.InstExpr)
+               w.op(ir.OFUNCINST)
+               w.pos(n.Pos())
+               w.expr(n.X)
+               w.uint64(uint64(len(n.Targs)))
+               for _, targ := range n.Targs {
+                       w.typ(targ.Type())
+               }
+               if go117ExportTypes {
+                       w.typ(n.Type())
+               }
+
+       case ir.OSELRECV2:
+               n := n.(*ir.AssignListStmt)
+               w.op(ir.OSELRECV2)
+               w.pos(n.Pos())
+               w.exprList(n.Lhs)
+               w.exprList(n.Rhs)
+
        default:
                base.Fatalf("cannot export %v (%d) node\n"+
                        "\t==> please file an issue and assign to gri@", n.Op(), int(n.Op()))
index 778ce4be12ab96d2c1999dfe35d35384c49a5012..3b725a226c46953eede35a39188e66daf4f0919d 100644 (file)
@@ -1582,6 +1582,26 @@ func (r *importReader) node() ir.Node {
        case ir.OEND:
                return nil
 
+       case ir.OFUNCINST:
+               pos := r.pos()
+               x := r.expr()
+               ntargs := r.uint64()
+               var targs []ir.Node
+               if ntargs > 0 {
+                       targs = make([]ir.Node, ntargs)
+                       for i := range targs {
+                               targs[i] = ir.TypeNode(r.typ())
+                       }
+               }
+               n := ir.NewInstExpr(pos, ir.OFUNCINST, x, targs)
+               if go117ExportTypes {
+                       n.SetType(r.typ())
+               }
+               return n
+
+       case ir.OSELRECV2:
+               return ir.NewAssignListStmt(r.pos(), ir.OSELRECV2, r.exprList(), r.exprList())
+
        default:
                base.Fatalf("cannot import %v (%d) node\n"+
                        "\t==> please file an issue and assign to gri@", op, int(op))
index d4a2988a7b0e46421e96949ebf8c3ada48081d04..0e120cf24278b99e0d791225f730d1747f8bd97a 100644 (file)
@@ -10,9 +10,9 @@ import (
        "fmt"
 )
 
-type _Gen[A any] func() (A, bool)
+type Gen[A any] func() (A, bool)
 
-func combine[T1, T2, T any](g1 _Gen[T1], g2 _Gen[T2], join func(T1, T2) T) _Gen[T] {
+func Combine[T1, T2, T any](g1 Gen[T1], g2 Gen[T2], join func(T1, T2) T) Gen[T] {
     return func() (T, bool) {
         var t T
         t1, ok := g1()
@@ -27,38 +27,38 @@ func combine[T1, T2, T any](g1 _Gen[T1], g2 _Gen[T2], join func(T1, T2) T) _Gen[
     }
 }
 
-type _Pair[A, B any] struct {
+type Pair[A, B any] struct {
        A A
        B B
 }
 
-func _NewPair[A, B any](a A, b B) _Pair[A, B] {
-       return _Pair[A, B]{a, b}
+func _NewPair[A, B any](a A, b B) Pair[A, B] {
+       return Pair[A, B]{a, b}
 }
 
-func _Combine2[A, B any](ga _Gen[A], gb _Gen[B]) _Gen[_Pair[A, B]] {
-    return combine(ga, gb, _NewPair[A, B])
+func Combine2[A, B any](ga Gen[A], gb Gen[B]) Gen[Pair[A, B]] {
+    return Combine(ga, gb, _NewPair[A, B])
 }
 
 func main() {
-       var g1 _Gen[int] = func() (int, bool) { return 3, true }
-       var g2 _Gen[string] = func() (string, bool) { return "x", false }
-       var g3 _Gen[string] = func() (string, bool) { return "y", true }
+       var g1 Gen[int] = func() (int, bool) { return 3, true }
+       var g2 Gen[string] = func() (string, bool) { return "x", false }
+       var g3 Gen[string] = func() (string, bool) { return "y", true }
 
-       gc := combine(g1, g2, _NewPair[int, string])
+       gc := Combine(g1, g2, _NewPair[int, string])
        if got, ok := gc(); ok {
                panic(fmt.Sprintf("got %v, %v, wanted -/false", got, ok))
        }
-       gc2 := _Combine2(g1, g2)
+       gc2 := Combine2(g1, g2)
        if got, ok := gc2(); ok {
                panic(fmt.Sprintf("got %v, %v, wanted -/false", got, ok))
        }
 
-       gc3 := combine(g1, g3, _NewPair[int, string])
+       gc3 := Combine(g1, g3, _NewPair[int, string])
        if got, ok := gc3(); !ok || got.A != 3 || got.B != "y" {
                panic(fmt.Sprintf("got %v, %v, wanted {3, y}, true", got, ok))
        }
-       gc4 := _Combine2(g1, g3)
+       gc4 := Combine2(g1, g3)
        if got, ok := gc4(); !ok || got.A != 3 || got.B != "y" {
                panic (fmt.Sprintf("got %v, %v, wanted {3, y}, true", got, ok))
        }
index 8d255ebdb83ea83e563426aefc228484b3a26728..f20514fb66ee8c119ffea35272b98974d251826a 100644 (file)
@@ -12,7 +12,7 @@ import "fmt"
 // argument
 type any interface{}
 
-type _Function[a, b any] interface {
+type Function[a, b any] interface {
        Apply(x a) b
 }
 
@@ -29,8 +29,8 @@ func (this pos) Apply(x int) bool {
 }
 
 type compose[a, b, c any] struct {
-       f _Function[a, b]
-       g _Function[b, c]
+       f Function[a, b]
+       g Function[b, c]
 }
 
 func (this compose[a, b, c]) Apply(x a) c {
@@ -47,52 +47,52 @@ func (this Int) Equal(that int) bool {
        return int(this) == that
 }
 
-type _List[a any] interface {
-       Match(casenil _Function[_Nil[a], any], casecons _Function[_Cons[a], any]) any
+type List[a any] interface {
+       Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any
 }
 
-type _Nil[a any] struct{
+type Nil[a any] struct{
 }
 
-func (xs _Nil[a]) Match(casenil _Function[_Nil[a], any], casecons _Function[_Cons[a], any]) any {
+func (xs Nil[a]) Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any {
        return casenil.Apply(xs)
 }
 
-type _Cons[a any] struct {
+type Cons[a any] struct {
        Head a
-       Tail _List[a]
+       Tail List[a]
 }
 
-func (xs _Cons[a]) Match(casenil _Function[_Nil[a], any], casecons _Function[_Cons[a], any]) any {
+func (xs Cons[a]) Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any {
        return casecons.Apply(xs)
 }
 
 type mapNil[a, b any] struct{
 }
 
-func (m mapNil[a, b]) Apply(_ _Nil[a]) any {
-       return _Nil[b]{}
+func (m mapNil[a, b]) Apply(_ Nil[a]) any {
+       return Nil[b]{}
 }
 
 type mapCons[a, b any] struct {
-       f _Function[a, b]
+       f Function[a, b]
 }
 
-func (m mapCons[a, b]) Apply(xs _Cons[a]) any {
-       return _Cons[b]{m.f.Apply(xs.Head), _Map[a, b](m.f, xs.Tail)}
+func (m mapCons[a, b]) Apply(xs Cons[a]) any {
+       return Cons[b]{m.f.Apply(xs.Head), Map[a, b](m.f, xs.Tail)}
 }
 
-func _Map[a, b any](f _Function[a, b], xs _List[a]) _List[b] {
-       return xs.Match(mapNil[a, b]{}, mapCons[a, b]{f}).(_List[b])
+func Map[a, b any](f Function[a, b], xs List[a]) List[b] {
+       return xs.Match(mapNil[a, b]{}, mapCons[a, b]{f}).(List[b])
 }
 
 func main() {
-       var xs _List[int] = _Cons[int]{3, _Cons[int]{6, _Nil[int]{}}}
-       var ys _List[int] = _Map[int, int](incr{-5}, xs)
-       var xz _List[bool] = _Map[int, bool](pos{}, ys)
-       cs1 := xz.(_Cons[bool])
-       cs2 := cs1.Tail.(_Cons[bool])
-       _, ok := cs2.Tail.(_Nil[bool])
+       var xs List[int] = Cons[int]{3, Cons[int]{6, Nil[int]{}}}
+       var ys List[int] = Map[int, int](incr{-5}, xs)
+       var xz List[bool] = Map[int, bool](pos{}, ys)
+       cs1 := xz.(Cons[bool])
+       cs2 := cs1.Tail.(Cons[bool])
+       _, ok := cs2.Tail.(Nil[bool])
        if cs1.Head != false || cs2.Head != true || !ok {
                panic(fmt.Sprintf("got %v, %v, %v, expected false, true, true",
                        cs1.Head, cs2.Head, ok))
diff --git a/test/typeparam/factimp.dir/a.go b/test/typeparam/factimp.dir/a.go
new file mode 100644 (file)
index 0000000..e11575e
--- /dev/null
@@ -0,0 +1,12 @@
+// 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
+
+func Fact[T interface { type int, int64, float64 }](n T) T {
+       if n == T(1) {
+               return T(1)
+       }
+       return n * Fact(n - T(1))
+}
diff --git a/test/typeparam/factimp.dir/main.go b/test/typeparam/factimp.dir/main.go
new file mode 100644 (file)
index 0000000..c223800
--- /dev/null
@@ -0,0 +1,26 @@
+// 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 (
+       "a"
+       "fmt"
+)
+
+func main() {
+       const want = 120
+
+       if got := a.Fact(5); got != want {
+               panic(fmt.Sprintf("got %d, want %d", got, want))
+       }
+
+       if got := a.Fact[int64](5); got != want {
+               panic(fmt.Sprintf("got %d, want %d", got, want))
+       }
+
+       if got := a.Fact(5.0); got != want {
+               panic(fmt.Sprintf("got %f, want %f", got, want))
+       }
+}
diff --git a/test/typeparam/factimp.go b/test/typeparam/factimp.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
index 83e65acdd006e20d0a6fc86be5d3b0a8841e4fe5..cb9b2613c33b71ec848c3e272f3ced771e15726f 100644 (file)
@@ -11,7 +11,7 @@ import (
 )
 
 // Index returns the index of x in s, or -1 if not found.
-func index[T comparable](s []T, x T) int {
+func Index[T comparable](s []T, x T) int {
        for i, v := range s {
                // v and x are type T, which has the comparable
                // constraint, so we can use == here.
@@ -30,17 +30,17 @@ func main() {
        want := 2
 
        vec1 := []string{"ab", "cd", "ef"}
-       if got := index(vec1, "ef"); got != want {
+       if got := Index(vec1, "ef"); got != want {
                panic(fmt.Sprintf("got %d, want %d", got, want))
        }
 
        vec2 := []byte{'c', '6', '@'}
-       if got := index(vec2, '@'); got != want {
+       if got := Index(vec2, '@'); got != want {
                panic(fmt.Sprintf("got %d, want %d", got, want))
        }
 
        vec3 := []*obj{&obj{2}, &obj{42}, &obj{1}}
-       if got := index(vec3, vec3[2]); got != want {
+       if got := Index(vec3, vec3[2]); got != want {
                panic(fmt.Sprintf("got %d, want %d", got, want))
        }
 }
index ea569751a679ea11624a6d0083409a83497302f1..a4118a0e819b5fb89f7464562cca321001291ad1 100644 (file)
@@ -1,3 +1,7 @@
+// 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 Ordered interface {
index 4c1aa3e4934ee4a674eda9f4c9a0a66f111bb5c3..d43ad508be51a85842062d4bad700ff4094176a2 100644 (file)
@@ -1,3 +1,7 @@
+// 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 (
index d53817521f30c8529fe9c3e4876eb7a5bddad553..3a03652cd8a5720f191f6916db58ced87f3ac991 100644 (file)
@@ -8,29 +8,29 @@ package main
 
 import "sync"
 
-// A _Lockable is a value that may be safely simultaneously accessed
+// A Lockable is a value that may be safely simultaneously accessed
 // from multiple goroutines via the Get and Set methods.
-type _Lockable[T any] struct {
+type Lockable[T any] struct {
        T
        mu sync.Mutex
 }
 
-// Get returns the value stored in a _Lockable.
-func (l *_Lockable[T]) get() T {
+// Get returns the value stored in a Lockable.
+func (l *Lockable[T]) get() T {
        l.mu.Lock()
        defer l.mu.Unlock()
        return l.T
 }
 
-// set sets the value in a _Lockable.
-func (l *_Lockable[T]) set(v T) {
+// set sets the value in a Lockable.
+func (l *Lockable[T]) set(v T) {
        l.mu.Lock()
        defer l.mu.Unlock()
        l.T = v
 }
 
 func main() {
-       sl := _Lockable[string]{T: "a"}
+       sl := Lockable[string]{T: "a"}
        if got := sl.get(); got != "a" {
                panic(got)
        }
@@ -39,7 +39,7 @@ func main() {
                panic(got)
        }
 
-       il := _Lockable[int]{T: 1}
+       il := Lockable[int]{T: 1}
        if got := il.get(); got != 1 {
                panic(got)
        }