add test for yesterday's interface rule change (interface/convert1.go).
move interface tests to subdirectory.
R=r
DELTA=1632 (827 added, 804 deleted, 1 changed)
OCL=29181
CL=29191
diff --git a/test/interface/bigdata.go b/test/interface/bigdata.go
new file mode 100644
index 0000000..674ea12
--- /dev/null
+++ b/test/interface/bigdata.go
@@ -0,0 +1,75 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 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.
+
+// check that big vs small, pointer vs not
+// interface methods work.
+
+package main
+
+type I interface { M() int64 }
+
+type BigPtr struct { a, b, c, d int64 }
+func (z *BigPtr) M() int64 { return z.a+z.b+z.c+z.d }
+
+type SmallPtr struct { a int32 }
+func (z *SmallPtr) M() int64 { return int64(z.a) }
+
+type IntPtr int32
+func (z *IntPtr) M() int64 { return int64(*z) }
+
+var bad bool
+
+func test(name string, i I) {
+ m := i.M();
+ if m != 12345 {
+ println(name, m);
+ bad = true;
+ }
+}
+
+func ptrs() {
+ var bigptr BigPtr = BigPtr{ 10000, 2000, 300, 45 };
+ var smallptr SmallPtr = SmallPtr{ 12345 };
+ var intptr IntPtr = 12345;
+
+// test("bigptr", bigptr);
+ test("&bigptr", &bigptr);
+// test("smallptr", smallptr);
+ test("&smallptr", &smallptr);
+// test("intptr", intptr);
+ test("&intptr", &intptr);
+}
+
+type Big struct { a, b, c, d int64 }
+func (z Big) M() int64 { return z.a+z.b+z.c+z.d }
+
+type Small struct { a int32 }
+func (z Small) M() int64 { return int64(z.a) }
+
+type Int int32
+func (z Int) M() int64 { return int64(z) }
+
+func nonptrs() {
+ var big Big = Big{ 10000, 2000, 300, 45 };
+ var small Small = Small{ 12345 };
+ var int Int = 12345;
+
+ test("big", big);
+ test("&big", &big);
+ test("small", small);
+ test("&small", &small);
+ test("int", int);
+ test("&int", &int);
+}
+
+func main() {
+ ptrs();
+ nonptrs();
+
+ if bad {
+ println("BUG: interface4");
+ }
+}
diff --git a/test/interface/convert.go b/test/interface/convert.go
new file mode 100644
index 0000000..f15f5ef
--- /dev/null
+++ b/test/interface/convert.go
@@ -0,0 +1,140 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 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.
+
+// Check uses of all the different interface
+// conversion runtime functions.
+
+package main
+
+type Stringer interface { String() string }
+type StringLengther interface { String() string; Length() int }
+type Empty interface { }
+
+type T string
+func (t T) String() string {
+ return string(t);
+}
+func (t T) Length() int {
+ return len(t);
+}
+
+type U string
+func (u U) String() string {
+ return string(u);
+}
+
+var t = T("hello")
+var u = U("goodbye")
+var e Empty
+var s Stringer = t
+var sl StringLengther = t
+var i int
+var ok bool
+
+func hello(s string) {
+ if s != "hello" {
+ panic("not hello: ", s);
+ }
+}
+
+func five(i int) {
+ if i != 5 {
+ panic("not 5: ", i);
+ }
+}
+
+func true(ok bool) {
+ if !ok {
+ panic("not true");
+ }
+}
+
+func false(ok bool) {
+ if ok {
+ panic("not false");
+ }
+}
+
+func main() {
+ // T2I
+ s = t;
+ hello(s.String());
+
+ // I2T
+ t = s.(T);
+ hello(t.String());
+
+ // T2E
+ e = t;
+
+ // E2T
+ t = e.(T);
+ hello(t.String());
+
+ // T2I again
+ sl = t;
+ hello(sl.String());
+ five(sl.Length());
+
+ // I2I static
+ s = sl;
+ hello(s.String());
+
+ // I2I dynamic
+ sl = s.(StringLengther);
+ hello(sl.String());
+ five(sl.Length());
+
+ // I2E (and E2T)
+ e = s;
+ hello(e.(T).String());
+
+ // E2I
+ s = e.(Stringer);
+ hello(s.String());
+
+ // I2T2 true
+ t, ok = s.(T);
+ true(ok);
+ hello(t.String());
+
+ // I2T2 false
+ var u1 U;
+ u1, ok = s.(U);
+ false(ok);
+
+ // I2I2 true
+ sl, ok = s.(StringLengther);
+ true(ok);
+ hello(sl.String());
+ five(sl.Length());
+
+ // I2I2 false (and T2I)
+ s = u;
+ sl, ok = s.(StringLengther);
+ false(ok);
+
+ // E2T2 true
+ t, ok = e.(T);
+ true(ok);
+ hello(t.String());
+
+ // E2T2 false
+ i, ok = e.(int);
+ false(ok);
+
+ // E2I2 true
+ sl, ok = e.(StringLengther);
+ true(ok);
+ hello(sl.String());
+ five(sl.Length());
+
+ // E2I2 false (and T2E)
+ e = u;
+ sl, ok = e.(StringLengther);
+ false(ok);
+}
+
diff --git a/test/interface/convert1.go b/test/interface/convert1.go
new file mode 100644
index 0000000..0eff6a9
--- /dev/null
+++ b/test/interface/convert1.go
@@ -0,0 +1,25 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 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.
+
+// Check that static interface conversion of
+// interface value nil succeeds.
+
+package main
+
+type R interface { R(); }
+type RW interface { R(); W(); }
+
+var e interface {}
+var r R;
+var rw RW;
+
+func main() {
+ r = r;
+ r = rw;
+ e = r;
+ e = rw;
+ rw = rw;
+}
diff --git a/test/interface/embed.go b/test/interface/embed.go
new file mode 100644
index 0000000..d216b89
--- /dev/null
+++ b/test/interface/embed.go
@@ -0,0 +1,82 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 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.
+
+// Check methods derived from embedded interface and *interface values.
+
+package main
+
+import "os"
+
+const Value = 1e12
+
+type Inter interface { M() int64 }
+
+type T int64
+func (t T) M() int64 { return int64(t) }
+var t = T(Value)
+var pt = &t
+var ti Inter = t
+var pti = &ti
+
+type S struct { Inter }
+var s = S{ ti }
+var ps = &s
+
+type SP struct { *Inter }
+var sp = SP{ &ti }
+var psp = &sp
+
+var i Inter
+var pi = &i
+
+var ok = true
+
+func check(v int64, s string) {
+ if v != Value {
+ println(s, v);
+ ok = false;
+ }
+}
+
+func main() {
+ check(t.M(), "t.M");
+ check(pt.M(), "pt.M");
+ check(ti.M(), "ti.M");
+ check(pti.M(), "pti.M");
+ check(s.M(), "s.M");
+ check(ps.M(), "ps.M");
+ check(sp.M(), "sp.M");
+ check(psp.M(), "psp.M");
+
+ i = t;
+ check(i.M(), "i.M - i = t");
+ check(pi.M(), "pi.M - i = t");
+
+ i = pt;
+ check(i.M(), "i.M - i = pt");
+ check(pi.M(), "pi.M - i = pt");
+
+ i = s;
+ check(i.M(), "i.M - i = s");
+ check(pi.M(), "pi.M - i = s");
+
+ i = ps;
+ check(i.M(), "i.M - i = ps");
+ check(pi.M(), "pi.M - i = ps");
+
+ i = sp;
+ check(i.M(), "i.M - i = sp");
+ check(pi.M(), "pi.M - i = sp");
+
+ i = psp;
+ check(i.M(), "i.M - i = psp");
+ check(pi.M(), "pi.M - i = psp");
+
+ if !ok {
+ println("BUG: interface10");
+ os.Exit(1)
+ }
+}
diff --git a/test/interface/explicit.go b/test/interface/explicit.go
new file mode 100644
index 0000000..3b5ed01
--- /dev/null
+++ b/test/interface/explicit.go
@@ -0,0 +1,34 @@
+// errchk $G $D/$F.go
+
+// Copyright 2009 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.
+
+// Static error messages about interface conversions.
+
+package main
+
+type T struct { a int }
+var t *T
+
+type I interface { M() }
+var i I
+
+type I2 interface { M(); N(); }
+var i2 I2;
+
+var e interface { };
+
+func main() {
+ e = t; // ok
+ t = e; // ERROR "need explicit"
+
+ // neither of these can work,
+ // because i has an extra method
+ // that t does not, so i cannot contain a t.
+ i = t; // ERROR "missing|incompatible|is not"
+ t = i; // ERROR "missing|incompatible|is not"
+
+ i = i2; // ok
+ i2 = i; // ERROR "need explicit"
+}
diff --git a/test/interface/fail.go b/test/interface/fail.go
new file mode 100644
index 0000000..1e37580
--- /dev/null
+++ b/test/interface/fail.go
@@ -0,0 +1,27 @@
+// $G $D/$F.go && $L $F.$A && ! ./$A.out
+
+// Copyright 2009 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.
+
+// Check that interface conversion fails when method is missing.
+
+package main
+
+type S struct
+
+type I interface {
+ Foo()
+}
+
+func main() {
+ var s *S;
+ var i I;
+ var e interface {};
+ e = s;
+ i = e.(I);
+}
+
+// hide S down here to avoid static warning
+type S struct {
+}
diff --git a/test/interface/fake.go b/test/interface/fake.go
new file mode 100644
index 0000000..a52d7a5
--- /dev/null
+++ b/test/interface/fake.go
@@ -0,0 +1,97 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 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.
+
+// Interface comparisons using types hidden
+// inside reflected-on structs.
+
+package main
+
+import "reflect"
+
+type T struct {
+ f float32;
+ g float32;
+
+ s string;
+ t string;
+
+ u uint32;
+ v uint32;
+
+ w uint32;
+ x uint32;
+
+ y uint32;
+ z uint32;
+}
+
+func add(s, t string) string {
+ return s + t;
+}
+
+func assert(b bool) {
+ if !b {
+ panic("assert");
+ }
+}
+
+func main() {
+ var x T;
+ x.f = 1.0;
+ x.g = x.f;
+ x.s = add("abc", "def");
+ x.t = add("abc", "def");
+ x.u = 1;
+ x.v = 2;
+ x.w = 1<<28;
+ x.x = 2<<28;
+ x.y = 0x12345678;
+ x.z = x.y;
+
+ // check mem and string
+ v := reflect.NewValue(x);
+ i := v.(reflect.StructValue).Field(0);
+ j := v.(reflect.StructValue).Field(1);
+ assert(i.Interface() == j.Interface());
+
+ s := v.(reflect.StructValue).Field(2);
+ t := v.(reflect.StructValue).Field(3);
+ assert(s.Interface() == t.Interface());
+
+ // make sure different values are different.
+ // make sure whole word is being compared,
+ // not just a single byte.
+ i = v.(reflect.StructValue).Field(4);
+ j = v.(reflect.StructValue).Field(5);
+ assert(i.Interface() != j.Interface());
+
+ i = v.(reflect.StructValue).Field(6);
+ j = v.(reflect.StructValue).Field(7);
+ assert(i.Interface() != j.Interface());
+
+ i = v.(reflect.StructValue).Field(8);
+ j = v.(reflect.StructValue).Field(9);
+ assert(i.Interface() == j.Interface());
+}
+
+/*
+comparing uncomparable type float32
+throw: interface compare
+
+panic PC=0x28ceb8 [1]
+throw+0x41 /Users/rsc/goX/src/runtime/runtime.c:54
+ throw(0x3014a, 0x0)
+ifaceeq+0x15c /Users/rsc/goX/src/runtime/iface.c:501
+ ifaceeq(0x2aa7c0, 0x0, 0x0, 0x0, 0x2aa7c0, ...)
+sys·ifaceeq+0x48 /Users/rsc/goX/src/runtime/iface.c:527
+ sys·ifaceeq(0x2aa7c0, 0x0, 0x0, 0x0, 0x2aa7c0, ...)
+main·main+0x190 /Users/rsc/goX/src/cmd/gc/x.go:10
+ main·main()
+mainstart+0xf /Users/rsc/goX/src/runtime/amd64/asm.s:53
+ mainstart()
+sys·Goexit /Users/rsc/goX/src/runtime/proc.c:124
+ sys·Goexit()
+*/
diff --git a/test/interface/pointer.go b/test/interface/pointer.go
new file mode 100644
index 0000000..202c37d
--- /dev/null
+++ b/test/interface/pointer.go
@@ -0,0 +1,37 @@
+// errchk $G $D/$F.go
+
+// Copyright 2009 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.
+
+// Check that interface{M()} = *interface{M()} produces a compiler error.
+
+package main
+
+type Inst interface {
+ Next() *Inst;
+}
+
+type Regexp struct {
+ code []Inst;
+ start Inst;
+}
+
+type Start struct {
+ foo *Inst;
+}
+
+func (start *Start) Next() *Inst { return nil }
+
+
+func AddInst(Inst) *Inst {
+ print("ok in addinst\n");
+ return nil
+}
+
+func main() {
+ re := new(Regexp);
+ print("call addinst\n");
+ var x Inst = AddInst(new(Start)); // ERROR "illegal|incompatible"
+ print("return from addinst\n");
+}
diff --git a/test/interface/receiver.go b/test/interface/receiver.go
new file mode 100644
index 0000000..438fea0
--- /dev/null
+++ b/test/interface/receiver.go
@@ -0,0 +1,104 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 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.
+
+// Implicit methods for embedded types.
+// Mixed pointer and non-pointer receivers.
+
+package main
+
+type T int
+var nv, np int
+
+func (t T) V() {
+ if t != 42 {
+ panic(t)
+ }
+ nv++
+}
+
+func (t *T) P() {
+ if *t != 42 {
+ panic(t, *t)
+ }
+ np++
+}
+
+type V interface { V() }
+type P interface { P(); V() }
+
+type S struct {
+ T;
+}
+
+type SP struct {
+ *T;
+}
+
+func main() {
+ var t T;
+ var v V;
+ var p P;
+
+ t = 42;
+
+ t.P();
+ t.V();
+
+ v = t;
+ v.V();
+
+ p = &t;
+ p.P();
+ p.V();
+
+ v = &t;
+ v.V();
+
+// p = t; // ERROR
+
+// println("--struct--");
+ var s S;
+ s.T = 42;
+ s.P();
+ s.V();
+
+ v = s;
+ s.V();
+
+ p = &s;
+ p.P();
+ p.V();
+
+ v = &s;
+ v.V();
+
+// p = s; // ERROR
+
+// println("--struct pointer--");
+ var sp SP;
+ sp.T = &t;
+ sp.P();
+ sp.V();
+
+ v = sp;
+ sp.V();
+
+ p = &sp;
+ p.P();
+ p.V();
+
+ v = &sp;
+ v.V();
+
+ p = sp; // not error
+ p.P();
+ p.V();
+
+ if nv != 13 || np != 7 {
+ panicln("bad count", nv, np)
+ }
+}
+
diff --git a/test/interface/receiver1.go b/test/interface/receiver1.go
new file mode 100644
index 0000000..7f257a3
--- /dev/null
+++ b/test/interface/receiver1.go
@@ -0,0 +1,43 @@
+// errchk $G $D/$F.go
+
+// Copyright 2009 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.
+
+// Error messages about missing implicit methods.
+
+package main
+
+type T int
+func (t T) V()
+func (t *T) P()
+
+type V interface { V() }
+type P interface { P(); V() }
+
+type S struct { T; }
+type SP struct { *T; }
+
+func main() {
+ var t T;
+ var v V;
+ var p P;
+ var s S;
+ var sp SP;
+
+ v = t;
+ p = t; // ERROR "is not|requires a pointer"
+ v = &t;
+ p = &t;
+
+ v = s;
+ p = s; // ERROR "is not|requires a pointer"
+ v = &s;
+ p = &s;
+
+ v = sp;
+ p = sp; // no error!
+ v = &sp;
+ p = &sp;
+}
+
diff --git a/test/interface/recursive.go b/test/interface/recursive.go
new file mode 100644
index 0000000..707cfcb
--- /dev/null
+++ b/test/interface/recursive.go
@@ -0,0 +1,24 @@
+// $G $D/$F.go || echo BUG: should compile
+
+// Copyright 2009 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.
+
+// Check mutually recursive interfaces
+
+package main
+
+type I2 interface
+
+type I1 interface {
+ foo() I2
+}
+
+type I2 interface {
+ bar() I1
+}
+
+type T int
+func (t T) bar() I1;
+func (t T) foo() I2 { return t }
+func (t T) bar() I1 { return t }
diff --git a/test/interface/returntype.go b/test/interface/returntype.go
new file mode 100644
index 0000000..93298bc
--- /dev/null
+++ b/test/interface/returntype.go
@@ -0,0 +1,25 @@
+// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should not succeed)
+
+// Copyright 2009 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.
+
+// Check methods with different return types.
+
+package main
+
+type S struct { a int }
+type T struct { b string }
+
+func (s *S) Name() int8 { return 1 }
+func (t *T) Name() int64 { return 64 }
+
+type I1 interface { Name() int8 }
+type I2 interface { Name() int64 }
+
+func main() {
+ var i1 I1;
+ var s *S;
+ i1 = s;
+ print(i1.(I2).Name())
+}
diff --git a/test/interface/struct.go b/test/interface/struct.go
new file mode 100644
index 0000000..49926f0
--- /dev/null
+++ b/test/interface/struct.go
@@ -0,0 +1,154 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG interface6
+
+// Copyright 2009 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.
+
+// Interface values containing structures.
+
+package main
+
+import "os"
+
+var fail int
+
+func check(b bool, msg string) {
+ if (!b) {
+ println("failure in", msg);
+ fail++;
+ }
+}
+
+type I1 interface { Get() int; Put(int); }
+
+type S1 struct { i int }
+func (p S1) Get() int { return p.i }
+func (p S1) Put(i int) { p.i = i }
+
+func f1() {
+ s := S1{1};
+ var i I1 = s;
+ i.Put(2);
+ check(i.Get() == 1, "f1 i");
+ check(s.i == 1, "f1 s");
+}
+
+func f2() {
+ s := S1{1};
+ var i I1 = &s;
+ i.Put(2);
+ check(i.Get() == 1, "f2 i");
+ check(s.i == 1, "f2 s");
+}
+
+func f3() {
+ s := &S1{1};
+ var i I1 = s;
+ i.Put(2);
+ check(i.Get() == 1, "f3 i");
+ check(s.i == 1, "f3 s");
+}
+
+type S2 struct { i int }
+func (p *S2) Get() int { return p.i }
+func (p *S2) Put(i int) { p.i = i }
+
+// func f4() {
+// s := S2{1};
+// var i I1 = s;
+// i.Put(2);
+// check(i.Get() == 2, "f4 i");
+// check(s.i == 1, "f4 s");
+// }
+
+func f5() {
+ s := S2{1};
+ var i I1 = &s;
+ i.Put(2);
+ check(i.Get() == 2, "f5 i");
+ check(s.i == 2, "f5 s");
+}
+
+func f6() {
+ s := &S2{1};
+ var i I1 = s;
+ i.Put(2);
+ check(i.Get() == 2, "f6 i");
+ check(s.i == 2, "f6 s");
+}
+
+type I2 interface { Get() int64; Put(int64); }
+
+type S3 struct { i, j, k, l int64 }
+func (p S3) Get() int64 { return p.l }
+func (p S3) Put(i int64) { p.l = i }
+
+func f7() {
+ s := S3{1, 2, 3, 4};
+ var i I2 = s;
+ i.Put(5);
+ check(i.Get() == 4, "f7 i");
+ check(s.l == 4, "f7 s");
+}
+
+func f8() {
+ s := S3{1, 2, 3, 4};
+ var i I2 = &s;
+ i.Put(5);
+ check(i.Get() == 4, "f8 i");
+ check(s.l == 4, "f8 s");
+}
+
+func f9() {
+ s := &S3{1, 2, 3, 4};
+ var i I2 = s;
+ i.Put(5);
+ check(i.Get() == 4, "f9 i");
+ check(s.l == 4, "f9 s");
+}
+
+type S4 struct { i, j, k, l int64 }
+func (p *S4) Get() int64 { return p.l }
+func (p *S4) Put(i int64) { p.l = i }
+
+// func f10() {
+// s := S4{1, 2, 3, 4};
+// var i I2 = s;
+// i.Put(5);
+// check(i.Get() == 5, "f10 i");
+// check(s.l == 4, "f10 s");
+// }
+
+func f11() {
+ s := S4{1, 2, 3, 4};
+ var i I2 = &s;
+ i.Put(5);
+ check(i.Get() == 5, "f11 i");
+ check(s.l == 5, "f11 s");
+}
+
+func f12() {
+ s := &S4{1, 2, 3, 4};
+ var i I2 = s;
+ i.Put(5);
+ check(i.Get() == 5, "f12 i");
+ check(s.l == 5, "f12 s");
+}
+
+func main() {
+ f1();
+ f2();
+ f3();
+// f4();
+ f5();
+ f6();
+ f7();
+ f8();
+ f9();
+// f10();
+ f11();
+ f12();
+ if fail > 0 {
+ os.Exit(1)
+ }
+}