aboutsummaryrefslogtreecommitdiff
path: root/src/pkg
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2011-04-20 14:07:13 -0700
committerRob Pike <r@golang.org>2011-04-20 14:07:13 -0700
commit220f83134aa6a8c21af1f255ecf4f595ca0598a2 (patch)
treeb8fb3d279a7054c90dfe7a7ad6e20a741241ed16 /src/pkg
parent8dad7fec1d3c12a7ff50c2ad5178f4b77d4e48ef (diff)
downloadgo-220f83134aa6a8c21af1f255ecf4f595ca0598a2.tar.xz
gob: use new Implements and AssignableTo methods in reflect
to improve the code and removea TODO. R=rsc CC=golang-dev https://golang.org/cl/4443054
Diffstat (limited to 'src/pkg')
-rw-r--r--src/pkg/gob/decode.go16
-rw-r--r--src/pkg/gob/type.go36
2 files changed, 15 insertions, 37 deletions
diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go
index b6d7cbea81..531285e40d 100644
--- a/src/pkg/gob/decode.go
+++ b/src/pkg/gob/decode.go
@@ -667,18 +667,12 @@ func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) {
dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint()))
}
-// setInterfaceValue sets an interface value to a concrete value through
-// reflection. If the concrete value does not implement the interface, the
-// setting will panic. This routine turns the panic into an error return.
-// This dance avoids manually checking that the value satisfies the
-// interface.
-// TODO(rsc): avoid panic+recover after fixing issue 327.
+// setInterfaceValue sets an interface value to a concrete value,
+// but first it checks that the assignment will succeed.
func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
- defer func() {
- if e := recover(); e != nil {
- error(e.(os.Error))
- }
- }()
+ if !value.Type().AssignableTo(ivalue.Type()) {
+ errorf("cannot assign value of type %s to %s", value.Type(), ivalue.Type())
+ }
ivalue.Set(value)
}
diff --git a/src/pkg/gob/type.go b/src/pkg/gob/type.go
index 8fd174841b..c337e40e85 100644
--- a/src/pkg/gob/type.go
+++ b/src/pkg/gob/type.go
@@ -74,8 +74,8 @@ func validUserType(rt reflect.Type) (ut *userTypeInfo, err os.Error) {
}
ut.indir++
}
- ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderCheck)
- ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderCheck)
+ ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderInterfaceType)
+ ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderInterfaceType)
userTypeCache[rt] = ut
return
}
@@ -85,32 +85,16 @@ const (
gobDecodeMethodName = "GobDecode"
)
-// implements returns whether the type implements the interface, as encoded
-// in the check function.
-func implements(typ reflect.Type, check func(typ reflect.Type) bool) bool {
- if typ.NumMethod() == 0 { // avoid allocations etc. unless there's some chance
- return false
- }
- return check(typ)
-}
-
-// gobEncoderCheck makes the type assertion a boolean function.
-func gobEncoderCheck(typ reflect.Type) bool {
- _, ok := reflect.Zero(typ).Interface().(GobEncoder)
- return ok
-}
-
-// gobDecoderCheck makes the type assertion a boolean function.
-func gobDecoderCheck(typ reflect.Type) bool {
- _, ok := reflect.Zero(typ).Interface().(GobDecoder)
- return ok
-}
+var (
+ gobEncoderInterfaceType = reflect.Typeof(new(GobEncoder)).Elem()
+ gobDecoderInterfaceType = reflect.Typeof(new(GobDecoder)).Elem()
+)
// implementsInterface reports whether the type implements the
-// interface. (The actual check is done through the provided function.)
+// gobEncoder/gobDecoder interface.
// It also returns the number of indirections required to get to the
// implementation.
-func implementsInterface(typ reflect.Type, check func(typ reflect.Type) bool) (success bool, indir int8) {
+func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) {
if typ == nil {
return
}
@@ -118,7 +102,7 @@ func implementsInterface(typ reflect.Type, check func(typ reflect.Type) bool) (s
// The type might be a pointer and we need to keep
// dereferencing to the base type until we find an implementation.
for {
- if implements(rt, check) {
+ if rt.Implements(gobEncDecType) {
return true, indir
}
if p := rt; p.Kind() == reflect.Ptr {
@@ -134,7 +118,7 @@ func implementsInterface(typ reflect.Type, check func(typ reflect.Type) bool) (s
// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
if typ.Kind() != reflect.Ptr {
// Not a pointer, but does the pointer work?
- if implements(reflect.PtrTo(typ), check) {
+ if reflect.PtrTo(typ).Implements(gobEncDecType) {
return true, -1
}
}