]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: small fixes for stenciling
authorDan Scales <danscales@google.com>
Wed, 10 Feb 2021 23:26:40 +0000 (15:26 -0800)
committerDan Scales <danscales@google.com>
Thu, 11 Feb 2021 21:46:39 +0000 (21:46 +0000)
 - Create the stencil name using targ.Type.String(), which handles cases
   where, for example, a type argument is a pointer to a named type,
   etc. *obj.

 - Set name.Def properly for a new stenciled func (have the symbol point
   back to the associated function node).  Will be required when exporting.

 - Add missing copying of Func field when making copies of Name nodes.
   (On purpose (it seems), Name nodes don't have a copy() function, so
   we have to copy all the needed fields explicitly.)

 - Deal with nil type in subster.node(), which is the type of the return
   value for a function that doesn't return anything.

 - Fix min to match standard want/go form, and add in float tests.  Changed
   Got -> got in bunch of other typeparam tests.

 - Add new tests index.go, settable.go, and smallest.go (similar to
   examples in the type param proposal), some of which need the above
   changes.

Change-Id: I09a72302bc1fd3635a326da92405222afa222e85
Reviewed-on: https://go-review.googlesource.com/c/go/+/291109
Trust: Dan Scales <danscales@google.com>
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/noder/stencil.go
test/typeparam/index.go [new file with mode: 0644]
test/typeparam/map.go
test/typeparam/min.go
test/typeparam/settable.go [new file with mode: 0644]
test/typeparam/smallest.go [new file with mode: 0644]
test/typeparam/stringer.go
test/typeparam/sum.go

index 2995496da189201ff4562976a478dcdde543456c..74ea2e0927d3b8469febd67167b2f5ee6780a95f 100644 (file)
@@ -80,7 +80,7 @@ func makeInstName(inst *ir.InstExpr) *types.Sym {
                if i > 0 {
                        b.WriteString(",")
                }
-               b.WriteString(targ.Name().Sym().Name)
+               b.WriteString(targ.Type().String())
        }
        b.WriteString("]")
        return typecheck.Lookup(b.String())
@@ -107,6 +107,7 @@ func genericSubst(name *types.Sym, inst *ir.InstExpr) *ir.Func {
        newf.Nname = ir.NewNameAt(inst.Pos(), name)
        newf.Nname.Func = newf
        newf.Nname.Defn = newf
+       name.Def = newf.Nname
 
        subst := &subster{
                newf:    newf,
@@ -160,6 +161,7 @@ func (subst *subster) node(n ir.Node) ir.Node {
                        m.SetType(newt)
                        m.Curfn = subst.newf
                        m.Class = name.Class
+                       m.Func = name.Func
                        subst.vars[name] = m
                        m.SetTypecheck(1)
                        return m
@@ -170,7 +172,17 @@ func (subst *subster) node(n ir.Node) ir.Node {
                }
                m := ir.Copy(x)
                if _, isExpr := m.(ir.Expr); isExpr {
-                       m.SetType(subst.typ(x.Type()))
+                       t := x.Type()
+                       if t == nil {
+                               // t can be nil only if this is a call that has no
+                               // return values, so allow that and otherwise give
+                               // an error.
+                               if _, isCallExpr := m.(*ir.CallExpr); !isCallExpr {
+                                       base.Fatalf(fmt.Sprintf("Nil type for %v", x))
+                               }
+                       } else {
+                               m.SetType(subst.typ(x.Type()))
+                       }
                }
                ir.EditChildren(m, edit)
 
diff --git a/test/typeparam/index.go b/test/typeparam/index.go
new file mode 100644 (file)
index 0000000..83e65ac
--- /dev/null
@@ -0,0 +1,46 @@
+// 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"
+)
+
+// Index returns the index of x in s, or -1 if not found.
+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.
+               if v == x {
+                       return i
+               }
+       }
+       return -1
+}
+
+type obj struct {
+       x int
+}
+
+func main() {
+       want := 2
+
+       vec1 := []string{"ab", "cd", "ef"}
+       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 {
+               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 {
+               panic(fmt.Sprintf("got %d, want %d", got, want))
+       }
+}
index 720a52ffbda2606d06787d982588fe3ef7043a74..72d05f08721113a59fae09de7c19c765f3960faa 100644 (file)
@@ -26,7 +26,7 @@ func main() {
        got := mapper([]int{1, 2, 3}, strconv.Itoa)
        want := []string{"1", "2", "3"}
        if !reflect.DeepEqual(got, want) {
-               panic(fmt.Sprintf("Got %s, want %s", got, want))
+               panic(fmt.Sprintf("got %s, want %s", got, want))
        }
 
        fgot := mapper([]float64{2.5, 2.3, 3.5}, func(f float64) string {
@@ -34,6 +34,6 @@ func main() {
        })
        fwant := []string{"2.5", "2.3", "3.5"}
        if !reflect.DeepEqual(fgot, fwant) {
-               panic(fmt.Sprintf("Got %s, want %s", fgot, fwant))
+               panic(fmt.Sprintf("got %s, want %s", fgot, fwant))
        }
 }
index 3bd92c5f3ea0d7ff7a5556117762a4c2a0ae8491..a3e4464a3039c85a9481d05225605f3d92b5c2af 100644 (file)
@@ -10,8 +10,11 @@ import (
        "fmt"
 )
 
+type Ordered interface {
+       type int, int64, float64
+}
 
-func min[T interface{ type int }](x, y T) T {
+func min[T Ordered](x, y T) T {
        if x < y {
                return x
        }
@@ -19,14 +22,20 @@ func min[T interface{ type int }](x, y T) T {
 }
 
 func main() {
-       want := 2
-       got := min[int](2, 3)
-       if want != got {
-               panic(fmt.Sprintf("Want %d, got %d", want, got))
+       const want = 2
+       if got := min[int](2, 3); got != want {
+               panic(fmt.Sprintf("got %d, want %d", got, want))
+       }
+
+       if got := min(2, 3); got != want {
+               panic(fmt.Sprintf("want %d, got %d", want, got))
+       }
+
+       if got := min[float64](3.5, 2.0); got != want {
+               panic(fmt.Sprintf("got %d, want %d", got, want))
        }
 
-       got = min(2, 3)
-       if want != got {
-               panic(fmt.Sprintf("Want %d, got %d", want, got))
+       if got := min(3.5, 2.0); got != want {
+               panic(fmt.Sprintf("got %d, want %d", got, want))
        }
 }
diff --git a/test/typeparam/settable.go b/test/typeparam/settable.go
new file mode 100644 (file)
index 0000000..3bd141f
--- /dev/null
@@ -0,0 +1,38 @@
+// 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"
+       "strconv"
+)
+
+func fromStrings3[T any](s []string, set func(*T, string)) []T {
+        results := make([]T, len(s))
+        for i, v := range s {
+                set(&results[i], v)
+        }
+        return results
+}
+
+type Settable int
+
+func (p *Settable) Set(s string) {
+        i, err := strconv.Atoi(s)
+        if err != nil {
+                panic(err)
+        }
+        *p = Settable(i)
+}
+
+func main() {
+        s := fromStrings3([]string{"1"},
+                func(p *Settable, s string) { p.Set(s) })
+        if len(s) != 1 || s[0] != 1 {
+                panic(fmt.Sprintf("got %v, want %v", s, []int{1}))
+        }
+}
diff --git a/test/typeparam/smallest.go b/test/typeparam/smallest.go
new file mode 100644 (file)
index 0000000..63dd9dd
--- /dev/null
@@ -0,0 +1,42 @@
+// 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"
+)
+
+type Ordered interface {
+       type int, int8, int16, int32, int64,
+               uint, uint8, uint16, uint32, uint64, uintptr,
+               float32, float64,
+               string
+}
+
+func smallest[T Ordered](s []T) T {
+       r := s[0] // panics if slice is empty
+       for _, v := range s[1:] {
+               if v < r {
+                       r = v
+               }
+       }
+       return r
+}
+
+func main() {
+       vec1 := []float64{5.3, 1.2, 32.8}
+       vec2 := []string{"abc", "def", "aaa"}
+
+       want1 := 1.2
+       if got := smallest(vec1); got != want1 {
+               panic(fmt.Sprintf("got %d, want %d", got, want1))
+       }
+       want2 := "aaa"
+       if got := smallest(vec2); got != want2 {
+               panic(fmt.Sprintf("got %d, want %d", got, want2))
+       }
+}
index 5086ac72f8cc35969b819da6d72f40406bcd1752..81290d599ecda5af09e36d6fc7d42f0e587f36e4 100644 (file)
@@ -73,16 +73,16 @@ func main() {
        got := stringify(x)
        want := []string{"1", "2", "3"}
        if !reflect.DeepEqual(got, want) {
-               panic(fmt.Sprintf("Got %s, want %s", got, want))
+               panic(fmt.Sprintf("got %s, want %s", got, want))
        }
 
        got = stringify2(x)
        if !reflect.DeepEqual(got, want) {
-               panic(fmt.Sprintf("Got %s, want %s", got, want))
+               panic(fmt.Sprintf("got %s, want %s", got, want))
        }
 
        got = stringify3(x)
        if !reflect.DeepEqual(got, want) {
-               panic(fmt.Sprintf("Got %s, want %s", got, want))
+               panic(fmt.Sprintf("got %s, want %s", got, want))
        }
 }
index 72511c2fe5b4ad9e1a86381dd4f6539017835004..f0f5e6aa07537b4627acf7d049341c835e4aaa00 100644 (file)
@@ -31,20 +31,20 @@ func main() {
        got := sum[int](vec1)
        want := vec1[0] + vec1[1]
        if got != want {
-               panic(fmt.Sprintf("Got %d, want %d", got, want))
+               panic(fmt.Sprintf("got %d, want %d", got, want))
        }
        got = sum(vec1)
        if want != got {
-               panic(fmt.Sprintf("Got %d, want %d", got, want))
+               panic(fmt.Sprintf("got %d, want %d", got, want))
        }
 
        fwant := vec2[0] + vec2[1]
        fgot := sum[float64](vec2)
        if abs(fgot - fwant) > 1e-10 {
-               panic(fmt.Sprintf("Got %f, want %f", fgot, fwant))
+               panic(fmt.Sprintf("got %f, want %f", fgot, fwant))
        }
        fgot = sum(vec2)
        if abs(fgot - fwant) > 1e-10 {
-               panic(fmt.Sprintf("Got %f, want %f", fgot, fwant))
+               panic(fmt.Sprintf("got %f, want %f", fgot, fwant))
        }
 }