1// This interpreter test is designed to run very quickly yet provide
2// some coverage of a broad selection of constructs.
3//
4// Validate this file with 'go run' after editing.
5// TODO(adonovan): break this into small files organized by theme.
6
7package main
8
9import (
10	"fmt"
11	"reflect"
12	"strings"
13)
14
15func init() {
16	// Call of variadic function with (implicit) empty slice.
17	if x := fmt.Sprint(); x != "" {
18		panic(x)
19	}
20}
21
22type empty interface{}
23
24type I interface {
25	f() int
26}
27
28type T struct{ z int }
29
30func (t T) f() int { return t.z }
31
32func use(interface{}) {}
33
34var counter = 2
35
36// Test initialization, including init blocks containing 'return'.
37// Assertion is in main.
38func init() {
39	counter *= 3
40	return
41	counter *= 3
42}
43
44func init() {
45	counter *= 5
46	return
47	counter *= 5
48}
49
50// Recursion.
51func fib(x int) int {
52	if x < 2 {
53		return x
54	}
55	return fib(x-1) + fib(x-2)
56}
57
58func fibgen(ch chan int) {
59	for x := 0; x < 10; x++ {
60		ch <- fib(x)
61	}
62	close(ch)
63}
64
65// Goroutines and channels.
66func init() {
67	ch := make(chan int)
68	go fibgen(ch)
69	var fibs []int
70	for v := range ch {
71		fibs = append(fibs, v)
72		if len(fibs) == 10 {
73			break
74		}
75	}
76	if x := fmt.Sprint(fibs); x != "[0 1 1 2 3 5 8 13 21 34]" {
77		panic(x)
78	}
79}
80
81// Test of aliasing.
82func init() {
83	type S struct {
84		a, b string
85	}
86
87	s1 := []string{"foo", "bar"}
88	s2 := s1 // creates an alias
89	s2[0] = "wiz"
90	if x := fmt.Sprint(s1, s2); x != "[wiz bar] [wiz bar]" {
91		panic(x)
92	}
93
94	pa1 := &[2]string{"foo", "bar"}
95	pa2 := pa1 // creates an alias
96	pa2[0] = "wiz"
97	if x := fmt.Sprint(*pa1, *pa2); x != "[wiz bar] [wiz bar]" {
98		panic(x)
99	}
100
101	a1 := [2]string{"foo", "bar"}
102	a2 := a1 // creates a copy
103	a2[0] = "wiz"
104	if x := fmt.Sprint(a1, a2); x != "[foo bar] [wiz bar]" {
105		panic(x)
106	}
107
108	t1 := S{"foo", "bar"}
109	t2 := t1 // copy
110	t2.a = "wiz"
111	if x := fmt.Sprint(t1, t2); x != "{foo bar} {wiz bar}" {
112		panic(x)
113	}
114}
115
116func main() {
117	print() // legal
118
119	if counter != 2*3*5 {
120		panic(counter)
121	}
122
123	// Test builtins (e.g. complex) preserve named argument types.
124	type N complex128
125	var n N
126	n = complex(1.0, 2.0)
127	if n != complex(1.0, 2.0) {
128		panic(n)
129	}
130	if x := reflect.TypeOf(n).String(); x != "main.N" {
131		panic(x)
132	}
133	if real(n) != 1.0 || imag(n) != 2.0 {
134		panic(n)
135	}
136
137	// Channel + select.
138	ch := make(chan int, 1)
139	select {
140	case ch <- 1:
141		// ok
142	default:
143		panic("couldn't send")
144	}
145	if <-ch != 1 {
146		panic("couldn't receive")
147	}
148	// A "receive" select-case that doesn't declare its vars.  (regression test)
149	anint := 0
150	ok := false
151	select {
152	case anint, ok = <-ch:
153	case anint = <-ch:
154	default:
155	}
156	_ = anint
157	_ = ok
158
159	// Anon structs with methods.
160	anon := struct{ T }{T: T{z: 1}}
161	if x := anon.f(); x != 1 {
162		panic(x)
163	}
164	var i I = anon
165	if x := i.f(); x != 1 {
166		panic(x)
167	}
168	// NB. precise output of reflect.Type.String is undefined.
169	if x := reflect.TypeOf(i).String(); x != "struct { main.T }" && x != "struct{main.T}" {
170		panic(x)
171	}
172
173	// fmt.
174	const message = "Hello, World!"
175	if fmt.Sprint("Hello", ", ", "World", "!") != message {
176		panic("oops")
177	}
178
179	// Type assertion.
180	type S struct {
181		f int
182	}
183	var e empty = S{f: 42}
184	switch v := e.(type) {
185	case S:
186		if v.f != 42 {
187			panic(v.f)
188		}
189	default:
190		panic(reflect.TypeOf(v))
191	}
192	if i, ok := e.(I); ok {
193		panic(i)
194	}
195
196	// Switch.
197	var x int
198	switch x {
199	case 1:
200		panic(x)
201		fallthrough
202	case 2, 3:
203		panic(x)
204	default:
205		// ok
206	}
207	// empty switch
208	switch {
209	}
210	// empty switch
211	switch {
212	default:
213	}
214	// empty switch
215	switch {
216	default:
217		fallthrough
218	case false:
219	}
220
221	// string -> []rune conversion.
222	use([]rune("foo"))
223
224	// Calls of form x.f().
225	type S2 struct {
226		f func() int
227	}
228	S2{f: func() int { return 1 }}.f() // field is a func value
229	T{}.f()                            // method call
230	i.f()                              // interface method invocation
231	(interface {
232		f() int
233	}(T{})).f() // anon interface method invocation
234
235	// Map lookup.
236	if v, ok := map[string]string{}["foo5"]; v != "" || ok {
237		panic("oops")
238	}
239
240	// Regression test: implicit address-taken struct literal
241	// inside literal map element.
242	_ = map[int]*struct{}{0: {}}
243}
244
245type mybool bool
246
247func (mybool) f() {}
248
249func init() {
250	type mybool bool
251	var b mybool
252	var i interface{} = b || b // result preserves types of operands
253	_ = i.(mybool)
254
255	i = false && b // result preserves type of "typed" operand
256	_ = i.(mybool)
257
258	i = b || true // result preserves type of "typed" operand
259	_ = i.(mybool)
260}
261
262func init() {
263	var x, y int
264	var b mybool = x == y // x==y is an untyped bool
265	b.f()
266}
267
268// Simple closures.
269func init() {
270	b := 3
271	f := func(a int) int {
272		return a + b
273	}
274	b++
275	if x := f(1); x != 5 { // 1+4 == 5
276		panic(x)
277	}
278	b++
279	if x := f(2); x != 7 { // 2+5 == 7
280		panic(x)
281	}
282	if b := f(1) < 16 || f(2) < 17; !b {
283		panic("oops")
284	}
285}
286
287// Shifts.
288func init() {
289	var i int64 = 1
290	var u uint64 = 1 << 32
291	if x := i << uint32(u); x != 1 {
292		panic(x)
293	}
294	if x := i << uint64(u); x != 0 {
295		panic(x)
296	}
297}
298
299// Implicit conversion of delete() key operand.
300func init() {
301	type I interface{}
302	m := make(map[I]bool)
303	m[1] = true
304	m[I(2)] = true
305	if len(m) != 2 {
306		panic(m)
307	}
308	delete(m, I(1))
309	delete(m, 2)
310	if len(m) != 0 {
311		panic(m)
312	}
313}
314
315// An I->I conversion always succeeds.
316func init() {
317	var x I
318	if I(x) != I(nil) {
319		panic("I->I conversion failed")
320	}
321}
322
323// An I->I type-assert fails iff the value is nil.
324func init() {
325	defer func() {
326		r := fmt.Sprint(recover())
327		// Exact error varies by toolchain.
328		if r != "runtime error: interface conversion: interface is nil, not main.I" &&
329			r != "interface conversion: interface is nil, not main.I" {
330			panic("I->I type assertion succeeded for nil value")
331		}
332	}()
333	var x I
334	_ = x.(I)
335}
336
337//////////////////////////////////////////////////////////////////////
338// Variadic bridge methods and interface thunks.
339
340type VT int
341
342var vcount = 0
343
344func (VT) f(x int, y ...string) {
345	vcount++
346	if x != 1 {
347		panic(x)
348	}
349	if len(y) != 2 || y[0] != "foo" || y[1] != "bar" {
350		panic(y)
351	}
352}
353
354type VS struct {
355	VT
356}
357
358type VI interface {
359	f(x int, y ...string)
360}
361
362func init() {
363	foobar := []string{"foo", "bar"}
364	var s VS
365	s.f(1, "foo", "bar")
366	s.f(1, foobar...)
367	if vcount != 2 {
368		panic("s.f not called twice")
369	}
370
371	fn := VI.f
372	fn(s, 1, "foo", "bar")
373	fn(s, 1, foobar...)
374	if vcount != 4 {
375		panic("I.f not called twice")
376	}
377}
378
379// Multiple labels on same statement.
380func multipleLabels() {
381	var trace []int
382	i := 0
383one:
384two:
385	for ; i < 3; i++ {
386		trace = append(trace, i)
387		switch i {
388		case 0:
389			continue two
390		case 1:
391			i++
392			goto one
393		case 2:
394			break two
395		}
396	}
397	if x := fmt.Sprint(trace); x != "[0 1 2]" {
398		panic(x)
399	}
400}
401
402func init() {
403	multipleLabels()
404}
405
406func init() {
407	// Struct equivalence ignores blank fields.
408	type s struct{ x, _, z int }
409	s1 := s{x: 1, z: 3}
410	s2 := s{x: 1, z: 3}
411	if s1 != s2 {
412		panic("not equal")
413	}
414}
415
416func init() {
417	// A slice var can be compared to const []T nil.
418	var i interface{} = []string{"foo"}
419	var j interface{} = []string(nil)
420	if i.([]string) == nil {
421		panic("expected i non-nil")
422	}
423	if j.([]string) != nil {
424		panic("expected j nil")
425	}
426	// But two slices cannot be compared, even if one is nil.
427	defer func() {
428		r := fmt.Sprint(recover())
429		if !(strings.Contains(r, "compar") && strings.Contains(r, "[]string")) {
430			panic("want panic from slice comparison, got " + r)
431		}
432	}()
433	_ = i == j // interface comparison recurses on types
434}
435
436func init() {
437	// Regression test for SSA renaming bug.
438	var ints []int
439	for range "foo" {
440		var x int
441		x++
442		ints = append(ints, x)
443	}
444	if fmt.Sprint(ints) != "[1 1 1]" {
445		panic(ints)
446	}
447}
448
449// Regression test for issue 6949:
450// []byte("foo") is not a constant since it allocates memory.
451func init() {
452	var r string
453	for i, b := range "ABC" {
454		x := []byte("abc")
455		x[i] = byte(b)
456		r += string(x)
457	}
458	if r != "AbcaBcabC" {
459		panic(r)
460	}
461}
462
463// Test of 3-operand x[lo:hi:max] slice.
464func init() {
465	s := []int{0, 1, 2, 3}
466	lenCapLoHi := func(x []int) [4]int { return [4]int{len(x), cap(x), x[0], x[len(x)-1]} }
467	if got := lenCapLoHi(s[1:3]); got != [4]int{2, 3, 1, 2} {
468		panic(got)
469	}
470	if got := lenCapLoHi(s[1:3:3]); got != [4]int{2, 2, 1, 2} {
471		panic(got)
472	}
473	max := 3
474	if "a"[0] == 'a' {
475		max = 2 // max is non-constant, even in SSA form
476	}
477	if got := lenCapLoHi(s[1:2:max]); got != [4]int{1, 1, 1, 1} {
478		panic(got)
479	}
480}
481
482var one = 1 // not a constant
483
484// Test makeslice.
485func init() {
486	check := func(s []string, wantLen, wantCap int) {
487		if len(s) != wantLen {
488			panic(len(s))
489		}
490		if cap(s) != wantCap {
491			panic(cap(s))
492		}
493	}
494	//                                       SSA form:
495	check(make([]string, 10), 10, 10)     // new([10]string)[:10]
496	check(make([]string, one), 1, 1)      // make([]string, one, one)
497	check(make([]string, 0, 10), 0, 10)   // new([10]string)[:0]
498	check(make([]string, 0, one), 0, 1)   // make([]string, 0, one)
499	check(make([]string, one, 10), 1, 10) // new([10]string)[:one]
500	check(make([]string, one, one), 1, 1) // make([]string, one, one)
501}
502
503// Test that a nice error is issued by indirection wrappers.
504func init() {
505	var ptr *T
506	var i I = ptr
507
508	defer func() {
509		r := fmt.Sprint(recover())
510		// Exact error varies by toolchain:
511		if r != "runtime error: value method (main.T).f called using nil *main.T pointer" &&
512			r != "value method (main.T).f called using nil *main.T pointer" {
513			panic("want panic from call with nil receiver, got " + r)
514		}
515	}()
516	i.f()
517	panic("unreachable")
518}
519
520// Regression test for a subtle bug in which copying values would causes
521// subcomponents of aggregate variables to change address, breaking
522// aliases.
523func init() {
524	type T struct{ f int }
525	var x T
526	p := &x.f
527	x = T{}
528	*p = 1
529	if x.f != 1 {
530		panic("lost store")
531	}
532	if p != &x.f {
533		panic("unstable address")
534	}
535}
536