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