From: Russ Cox Date: Tue, 12 May 2009 23:08:16 +0000 (-0700) Subject: update reflect for upcoming interface representation change. X-Git-Tag: weekly.2009-11-06~1660 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=28516d4c78706a805000b4a119f30fca90d68fb9;p=gostls13.git update reflect for upcoming interface representation change. test case for new change. both work with the current compiler too. R=r DELTA=150 (145 added, 2 deleted, 3 changed) OCL=28703 CL=28715 --- diff --git a/src/lib/reflect/value.go b/src/lib/reflect/value.go index c21f28e770..2772ff1e17 100644 --- a/src/lib/reflect/value.go +++ b/src/lib/reflect/value.go @@ -782,7 +782,16 @@ type interfaceValueStruct struct { } func (v *interfaceValueStruct) Get() interface{} { - return *(*interface{})(v.addr) + // There are two different representations of interface values, + // one if the interface type has methods and one if it doesn't. + // These two representations require different expressions + // to extract correctly. + if v.Type().(InterfaceType).Len() == 0 { + // Extract as interface value without methods. + return *(*interface{})(v.addr) + } + // Extract from v.addr as interface value with methods. + return *(*interface{ m() })(v.addr) } func (v *interfaceValueStruct) Value() Value { diff --git a/test/interface11.go b/test/interface11.go new file mode 100644 index 0000000000..f15f5ef0fb --- /dev/null +++ b/test/interface11.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/interface4.go b/test/interface4.go index b871309379..674ea12761 100644 --- a/test/interface4.go +++ b/test/interface4.go @@ -9,8 +9,6 @@ package main -import "os" - type I interface { M() int64 } type BigPtr struct { a, b, c, d int64 } @@ -72,6 +70,6 @@ func main() { nonptrs(); if bad { - os.Exit(1) + println("BUG: interface4"); } }