if i > 0 {
                        b.WriteString(",")
                }
-               b.WriteString(targ.Name().Sym().Name)
+               b.WriteString(targ.Type().String())
        }
        b.WriteString("]")
        return typecheck.Lookup(b.String())
        newf.Nname = ir.NewNameAt(inst.Pos(), name)
        newf.Nname.Func = newf
        newf.Nname.Defn = newf
+       name.Def = newf.Nname
 
        subst := &subster{
                newf:    newf,
                        m.SetType(newt)
                        m.Curfn = subst.newf
                        m.Class = name.Class
+                       m.Func = name.Func
                        subst.vars[name] = m
                        m.SetTypecheck(1)
                        return m
                }
                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)
 
 
--- /dev/null
+// 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))
+       }
+}
 
        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 {
        })
        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))
        }
 }
 
        "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
        }
 }
 
 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))
        }
 }
 
--- /dev/null
+// 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}))
+        }
+}
 
--- /dev/null
+// 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))
+       }
+}
 
        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))
        }
 }
 
        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))
        }
 }