From 544cf759040667768348ea516bcb2f72b08e573f Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Tue, 22 Mar 2011 11:43:00 -0700 Subject: [PATCH] gob: use pointers in bootstrapType so interfaces behave properly and don't lead to a nil reflect.Type. Fixes #1626. R=rsc CC=golang-dev https://golang.org/cl/4289062 --- src/pkg/gob/type.go | 58 ++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/src/pkg/gob/type.go b/src/pkg/gob/type.go index 0001f0c2e2..9c62107b84 100644 --- a/src/pkg/gob/type.go +++ b/src/pkg/gob/type.go @@ -222,22 +222,45 @@ func (t *CommonType) name() string { return t.Name } var ( // Primordial types, needed during initialization. - tBool = bootstrapType("bool", false, 1) - tInt = bootstrapType("int", int(0), 2) - tUint = bootstrapType("uint", uint(0), 3) - tFloat = bootstrapType("float", float64(0), 4) - tBytes = bootstrapType("bytes", make([]byte, 0), 5) - tString = bootstrapType("string", "", 6) - tComplex = bootstrapType("complex", 0+0i, 7) - tInterface = bootstrapType("interface", interface{}(nil), 8) + // Always passed as pointers so the interface{} type + // goes through without losing its interfaceness. + tBool = bootstrapType("bool", (*bool)(nil), 1) + tInt = bootstrapType("int", (*int)(nil), 2) + tUint = bootstrapType("uint", (*uint)(nil), 3) + tFloat = bootstrapType("float", (*float64)(nil), 4) + tBytes = bootstrapType("bytes", (*[]byte)(nil), 5) + tString = bootstrapType("string", (*string)(nil), 6) + tComplex = bootstrapType("complex", (*complex128)(nil), 7) + tInterface = bootstrapType("interface", (*interface{})(nil), 8) // Reserve some Ids for compatible expansion - tReserved7 = bootstrapType("_reserved1", struct{ r7 int }{}, 9) - tReserved6 = bootstrapType("_reserved1", struct{ r6 int }{}, 10) - tReserved5 = bootstrapType("_reserved1", struct{ r5 int }{}, 11) - tReserved4 = bootstrapType("_reserved1", struct{ r4 int }{}, 12) - tReserved3 = bootstrapType("_reserved1", struct{ r3 int }{}, 13) - tReserved2 = bootstrapType("_reserved1", struct{ r2 int }{}, 14) - tReserved1 = bootstrapType("_reserved1", struct{ r1 int }{}, 15) + tReserved7 = bootstrapType("_reserved1", (*struct { + r7 int + })(nil), + 9) + tReserved6 = bootstrapType("_reserved1", (*struct { + r6 int + })(nil), + 10) + tReserved5 = bootstrapType("_reserved1", (*struct { + r5 int + })(nil), + 11) + tReserved4 = bootstrapType("_reserved1", (*struct { + r4 int + })(nil), + 12) + tReserved3 = bootstrapType("_reserved1", (*struct { + r3 int + })(nil), + 13) + tReserved2 = bootstrapType("_reserved1", (*struct { + r2 int + })(nil), + 14) + tReserved1 = bootstrapType("_reserved1", (*struct { + r1 int + })(nil), + 15) ) // Predefined because it's needed by the Decoder @@ -564,9 +587,10 @@ func checkId(want, got typeId) { } } -// used for building the basic types; called only from init() +// used for building the basic types; called only from init(). the incoming +// interface always refers to a pointer. func bootstrapType(name string, e interface{}, expect typeId) typeId { - rt := reflect.Typeof(e) + rt := reflect.Typeof(e).(*reflect.PtrType).Elem() _, present := types[rt] if present { panic("bootstrap type already present: " + name + ", " + rt.String())