builtins_test.go raw

   1  // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
   2  // Source: ../../cmd/compile/internal/types2/builtins_test.go
   3  
   4  // Copyright 2013 The Go Authors. All rights reserved.
   5  // Use of this source code is governed by a BSD-style
   6  // license that can be found in the LICENSE file.
   7  
   8  package types_test
   9  
  10  import (
  11  	"fmt"
  12  	"go/ast"
  13  	"testing"
  14  
  15  	. "go/types"
  16  )
  17  
  18  var builtinCalls = []struct {
  19  	name, src, sig string
  20  }{
  21  	{"append", `var s []int; _ = append(s)`, `func([]int, ...int) []int`},
  22  	{"append", `var s []int; _ = append(s, 0)`, `func([]int, ...int) []int`},
  23  	{"append", `var s []int; _ = (append)(s, 0)`, `func([]int, ...int) []int`},
  24  	{"append", `var s []byte; _ = ((append))(s, 0)`, `func([]byte, ...byte) []byte`},
  25  	{"append", `var s []byte; _ = append(s, "foo"...)`, `func([]byte, string...) []byte`},
  26  	{"append", `type T []byte; var s T; var str string; _ = append(s, str...)`, `func(p.T, string...) p.T`},
  27  	{"append", `type T []byte; type U string; var s T; var str U; _ = append(s, str...)`, `func(p.T, p.U...) p.T`},
  28  
  29  	{"cap", `var s [10]int; _ = cap(s)`, `invalid type`},  // constant
  30  	{"cap", `var s [10]int; _ = cap(&s)`, `invalid type`}, // constant
  31  	{"cap", `var s []int64; _ = cap(s)`, `func([]int64) int`},
  32  	{"cap", `var c chan<-bool; _ = cap(c)`, `func(chan<- bool) int`},
  33  	{"cap", `type S []byte; var s S; _ = cap(s)`, `func(p.S) int`},
  34  	{"cap", `var s P; _ = cap(s)`, `func(P) int`},
  35  
  36  	{"len", `_ = len("foo")`, `invalid type`}, // constant
  37  	{"len", `var s string; _ = len(s)`, `func(string) int`},
  38  	{"len", `var s [10]int; _ = len(s)`, `invalid type`},  // constant
  39  	{"len", `var s [10]int; _ = len(&s)`, `invalid type`}, // constant
  40  	{"len", `var s []int64; _ = len(s)`, `func([]int64) int`},
  41  	{"len", `var c chan<-bool; _ = len(c)`, `func(chan<- bool) int`},
  42  	{"len", `var m map[string]float32; _ = len(m)`, `func(map[string]float32) int`},
  43  	{"len", `type S []byte; var s S; _ = len(s)`, `func(p.S) int`},
  44  	{"len", `var s P; _ = len(s)`, `func(P) int`},
  45  
  46  	{"clear", `var m map[float64]int; clear(m)`, `func(map[float64]int)`},
  47  	{"clear", `var s []byte; clear(s)`, `func([]byte)`},
  48  
  49  	{"close", `var c chan int; close(c)`, `func(chan int)`},
  50  	{"close", `var c chan<- chan string; close(c)`, `func(chan<- chan string)`},
  51  
  52  	{"complex", `_ = complex(1, 0)`, `invalid type`}, // constant
  53  	{"complex", `var re float32; _ = complex(re, 1.0)`, `func(float32, float32) complex64`},
  54  	{"complex", `var im float64; _ = complex(1, im)`, `func(float64, float64) complex128`},
  55  	{"complex", `type F32 float32; var re, im F32; _ = complex(re, im)`, `func(p.F32, p.F32) complex64`},
  56  	{"complex", `type F64 float64; var re, im F64; _ = complex(re, im)`, `func(p.F64, p.F64) complex128`},
  57  
  58  	{"copy", `var src, dst []byte; copy(dst, src)`, `func([]byte, []byte) int`},
  59  	{"copy", `type T [][]int; var src, dst T; _ = copy(dst, src)`, `func(p.T, p.T) int`},
  60  	{"copy", `var src string; var dst []byte; copy(dst, src)`, `func([]byte, string) int`},
  61  	{"copy", `type T string; type U []byte; var src T; var dst U; copy(dst, src)`, `func(p.U, p.T) int`},
  62  	{"copy", `var dst []byte; copy(dst, "hello")`, `func([]byte, string) int`},
  63  
  64  	{"delete", `var m map[string]bool; delete(m, "foo")`, `func(map[string]bool, string)`},
  65  	{"delete", `type (K string; V int); var m map[K]V; delete(m, "foo")`, `func(map[p.K]p.V, p.K)`},
  66  
  67  	{"imag", `_ = imag(1i)`, `invalid type`}, // constant
  68  	{"imag", `var c complex64; _ = imag(c)`, `func(complex64) float32`},
  69  	{"imag", `var c complex128; _ = imag(c)`, `func(complex128) float64`},
  70  	{"imag", `type C64 complex64; var c C64; _ = imag(c)`, `func(p.C64) float32`},
  71  	{"imag", `type C128 complex128; var c C128; _ = imag(c)`, `func(p.C128) float64`},
  72  
  73  	{"real", `_ = real(1i)`, `invalid type`}, // constant
  74  	{"real", `var c complex64; _ = real(c)`, `func(complex64) float32`},
  75  	{"real", `var c complex128; _ = real(c)`, `func(complex128) float64`},
  76  	{"real", `type C64 complex64; var c C64; _ = real(c)`, `func(p.C64) float32`},
  77  	{"real", `type C128 complex128; var c C128; _ = real(c)`, `func(p.C128) float64`},
  78  
  79  	{"make", `_ = make([]int, 10)`, `func([]int, int) []int`},
  80  	{"make", `type T []byte; _ = make(T, 10, 20)`, `func(p.T, int, int) p.T`},
  81  
  82  	// go.dev/issue/37349
  83  	{"make", `              _ = make([]int, 0   )`, `func([]int, int) []int`},
  84  	{"make", `var l    int; _ = make([]int, l   )`, `func([]int, int) []int`},
  85  	{"make", `              _ = make([]int, 0, 0)`, `func([]int, int, int) []int`},
  86  	{"make", `var l    int; _ = make([]int, l, 0)`, `func([]int, int, int) []int`},
  87  	{"make", `var    c int; _ = make([]int, 0, c)`, `func([]int, int, int) []int`},
  88  	{"make", `var l, c int; _ = make([]int, l, c)`, `func([]int, int, int) []int`},
  89  
  90  	// go.dev/issue/37393
  91  	{"make", `                _ = make([]int       , 0   )`, `func([]int, int) []int`},
  92  	{"make", `var l    byte ; _ = make([]int8      , l   )`, `func([]int8, byte) []int8`},
  93  	{"make", `                _ = make([]int16     , 0, 0)`, `func([]int16, int, int) []int16`},
  94  	{"make", `var l    int16; _ = make([]string    , l, 0)`, `func([]string, int16, int) []string`},
  95  	{"make", `var    c int32; _ = make([]float64   , 0, c)`, `func([]float64, int, int32) []float64`},
  96  	{"make", `var l, c uint ; _ = make([]complex128, l, c)`, `func([]complex128, uint, uint) []complex128`},
  97  
  98  	// go.dev/issue/45667
  99  	{"make", `const l uint = 1; _ = make([]int, l)`, `func([]int, uint) []int`},
 100  
 101  	{"max", `               _ = max(0        )`, `invalid type`}, // constant
 102  	{"max", `var x int    ; _ = max(x        )`, `func(int) int`},
 103  	{"max", `var x int    ; _ = max(0, x     )`, `func(int, int) int`},
 104  	{"max", `var x string ; _ = max("a", x   )`, `func(string, string) string`},
 105  	{"max", `var x float32; _ = max(0, 1.0, x)`, `func(float32, float32, float32) float32`},
 106  
 107  	{"min", `               _ = min(0        )`, `invalid type`}, // constant
 108  	{"min", `var x int    ; _ = min(x        )`, `func(int) int`},
 109  	{"min", `var x int    ; _ = min(0, x     )`, `func(int, int) int`},
 110  	{"min", `var x string ; _ = min("a", x   )`, `func(string, string) string`},
 111  	{"min", `var x float32; _ = min(0, 1.0, x)`, `func(float32, float32, float32) float32`},
 112  
 113  	{"new", `_ = new(int)`, `func(int) *int`},
 114  	{"new", `type T struct{}; _ = new(T)`, `func(p.T) *p.T`},
 115  
 116  	{"panic", `panic(0)`, `func(interface{})`},
 117  	{"panic", `panic("foo")`, `func(interface{})`},
 118  
 119  	{"print", `print()`, `func()`},
 120  	{"print", `print(0)`, `func(int)`},
 121  	{"print", `print(1, 2.0, "foo", true)`, `func(int, float64, string, bool)`},
 122  
 123  	{"println", `println()`, `func()`},
 124  	{"println", `println(0)`, `func(int)`},
 125  	{"println", `println(1, 2.0, "foo", true)`, `func(int, float64, string, bool)`},
 126  
 127  	{"recover", `recover()`, `func() interface{}`},
 128  	{"recover", `_ = recover()`, `func() interface{}`},
 129  
 130  	{"Add", `var p unsafe.Pointer; _ = unsafe.Add(p, -1.0)`, `func(unsafe.Pointer, int) unsafe.Pointer`},
 131  	{"Add", `var p unsafe.Pointer; var n uintptr; _ = unsafe.Add(p, n)`, `func(unsafe.Pointer, uintptr) unsafe.Pointer`},
 132  	{"Add", `_ = unsafe.Add(nil, 0)`, `func(unsafe.Pointer, int) unsafe.Pointer`},
 133  
 134  	{"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`},                 // constant
 135  	{"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant
 136  	{"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(P) uintptr`},
 137  
 138  	{"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`},           // constant
 139  	{"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant
 140  	{"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(P) uintptr`},
 141  
 142  	{"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`},                 // constant
 143  	{"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant
 144  	{"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(P) uintptr`},
 145  
 146  	{"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`},
 147  	{"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`},
 148  	{"Slice", `type B *byte; var b B; _ = unsafe.Slice(b, 0)`, `func(*byte, int) []byte`},
 149  
 150  	{"SliceData", "var s []int; _ = unsafe.SliceData(s)", `func([]int) *int`},
 151  	{"SliceData", "type S []int; var s S; _ = unsafe.SliceData(s)", `func([]int) *int`},
 152  
 153  	{"String", `var p *byte; _ = unsafe.String(p, 1)`, `func(*byte, int) string`},
 154  	{"String", `type B *byte; var b B; _ = unsafe.String(b, 0)`, `func(*byte, int) string`},
 155  
 156  	{"StringData", `var s string; _ = unsafe.StringData(s)`, `func(string) *byte`},
 157  	{"StringData", `_ = unsafe.StringData("foo")`, `func(string) *byte`},
 158  
 159  	{"assert", `assert(true)`, `invalid type`},                                    // constant
 160  	{"assert", `type B bool; const pred B = 1 < 2; assert(pred)`, `invalid type`}, // constant
 161  
 162  	// no tests for trace since it produces output as a side-effect
 163  }
 164  
 165  func TestBuiltinSignatures(t *testing.T) {
 166  	DefPredeclaredTestFuncs()
 167  
 168  	seen := map[string]bool{"trace": true} // no test for trace built-in; add it manually
 169  	for _, call := range builtinCalls {
 170  		testBuiltinSignature(t, call.name, call.src, call.sig)
 171  		seen[call.name] = true
 172  	}
 173  
 174  	// make sure we didn't miss one
 175  	for _, name := range Universe.Names() {
 176  		if _, ok := Universe.Lookup(name).(*Builtin); ok && !seen[name] {
 177  			t.Errorf("missing test for %s", name)
 178  		}
 179  	}
 180  	for _, name := range Unsafe.Scope().Names() {
 181  		if _, ok := Unsafe.Scope().Lookup(name).(*Builtin); ok && !seen[name] {
 182  			t.Errorf("missing test for unsafe.%s", name)
 183  		}
 184  	}
 185  }
 186  
 187  func testBuiltinSignature(t *testing.T, name, src0, want string) {
 188  	src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P ~[]byte]() { %s }`, src0)
 189  
 190  	uses := make(map[*ast.Ident]Object)
 191  	types := make(map[ast.Expr]TypeAndValue)
 192  	mustTypecheck(src, nil, &Info{Uses: uses, Types: types})
 193  
 194  	// find called function
 195  	n := 0
 196  	var fun ast.Expr
 197  	for x := range types {
 198  		if call, _ := x.(*ast.CallExpr); call != nil {
 199  			fun = call.Fun
 200  			n++
 201  		}
 202  	}
 203  	if n != 1 {
 204  		t.Errorf("%s: got %d CallExprs; want 1", src0, n)
 205  		return
 206  	}
 207  
 208  	// check recorded types for fun and descendents (may be parenthesized)
 209  	for {
 210  		// the recorded type for the built-in must match the wanted signature
 211  		typ := types[fun].Type
 212  		if typ == nil {
 213  			t.Errorf("%s: no type recorded for %s", src0, ExprString(fun))
 214  			return
 215  		}
 216  		if got := typ.String(); got != want {
 217  			t.Errorf("%s: got type %s; want %s", src0, got, want)
 218  			return
 219  		}
 220  
 221  		// called function must be a (possibly parenthesized, qualified)
 222  		// identifier denoting the expected built-in
 223  		switch p := fun.(type) {
 224  		case *ast.Ident:
 225  			obj := uses[p]
 226  			if obj == nil {
 227  				t.Errorf("%s: no object found for %s", src0, p.Name)
 228  				return
 229  			}
 230  			bin, _ := obj.(*Builtin)
 231  			if bin == nil {
 232  				t.Errorf("%s: %s does not denote a built-in", src0, p.Name)
 233  				return
 234  			}
 235  			if bin.Name() != name {
 236  				t.Errorf("%s: got built-in %s; want %s", src0, bin.Name(), name)
 237  				return
 238  			}
 239  			return // we're done
 240  
 241  		case *ast.ParenExpr:
 242  			fun = p.X // unpack
 243  
 244  		case *ast.SelectorExpr:
 245  			// built-in from package unsafe - ignore details
 246  			return // we're done
 247  
 248  		default:
 249  			t.Errorf("%s: invalid function call", src0)
 250  			return
 251  		}
 252  	}
 253  }
 254