aboutsummaryrefslogtreecommitdiffhomepage
path: root/testdata/interface.go
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2018-10-07 02:06:48 +0200
committerAyke van Laethem <[email protected]>2018-10-07 02:06:48 +0200
commit4957db89f49dfd4aba6afbb8aa4846d54b26f614 (patch)
treea89b71c750d6232a5cb68d0552bc7a097cec3fbe /testdata/interface.go
parent482c5633dd34af850d384a74559ed9d977417c7c (diff)
downloadtinygo-4957db89f49dfd4aba6afbb8aa4846d54b26f614.tar.gz
tinygo-4957db89f49dfd4aba6afbb8aa4846d54b26f614.zip
compiler: fix interface calls for big underlying values
When the underlying value of an interface does not fit in a pointer, a pointer to the value was correctly inserted in the heap. However, the receiving method still assumed it got the underlying value instead of a pointer to it leading to a crash. This commit inserts wrapper functions for method calls on interfaces. The bug wasn't obvious as on a 64-bit system, the underlying value was almost always put directly in the interface. However, it led to a crash on the AVR platform where pointer are (usually) just 16 bits making it far more likely that underlying values cannot be directly stored in an interface.
Diffstat (limited to 'testdata/interface.go')
-rw-r--r--testdata/interface.go87
1 files changed, 87 insertions, 0 deletions
diff --git a/testdata/interface.go b/testdata/interface.go
new file mode 100644
index 000000000..f24a995fa
--- /dev/null
+++ b/testdata/interface.go
@@ -0,0 +1,87 @@
+package main
+
+func main() {
+ thing := &Thing{"foo"}
+ println("thing:", thing.String())
+ thing.Print()
+ printItf(5)
+ printItf(byte('x'))
+ printItf("foo")
+ printItf(*thing)
+ printItf(thing)
+ printItf(Stringer(thing))
+ printItf(Number(3))
+ array := Array([4]uint32{1, 7, 11, 13})
+ printItf(array)
+ s := Stringer(thing)
+ println("Stringer.String():", s.String())
+ var itf interface{} = s
+ println("Stringer.(*Thing).String():", itf.(Stringer).String())
+}
+
+func printItf(val interface{}) {
+ switch val := val.(type) {
+ case Doubler:
+ println("is Doubler:", val.Double())
+ case Tuple:
+ println("is Tuple:", val.Nth(0), val.Nth(1), val.Nth(2), val.Nth(3))
+ val.Print()
+ case int:
+ println("is int:", val)
+ case byte:
+ println("is byte:", val)
+ case string:
+ println("is string:", val)
+ case Thing:
+ println("is Thing:", val.String())
+ case *Thing:
+ println("is *Thing:", val.String())
+ case Foo:
+ println("is Foo:", val)
+ default:
+ println("is ?")
+ }
+}
+
+type Thing struct {
+ name string
+}
+
+func (t Thing) String() string {
+ return t.name
+}
+
+func (t Thing) Print() {
+ println("Thing.Print:", t.name)
+}
+
+type Stringer interface {
+ String() string
+}
+
+type Foo int
+
+type Number int
+
+func (n Number) Double() int {
+ return int(n) * 2
+}
+
+type Doubler interface {
+ Double() int
+}
+
+type Tuple interface {
+ Nth(int) uint32
+ Print()
+}
+
+type Array [4]uint32
+
+func (a Array) Nth(n int) uint32 {
+ return a[n]
+}
+
+func (a Array) Print() {
+ println("Array len:", len(a))
+}