handle unsupported types safely.

R=rsc
DELTA=154  (71 added, 6 deleted, 77 changed)
OCL=32483
CL=32492
diff --git a/src/pkg/gob/encode.go b/src/pkg/gob/encode.go
index be35997..1af79b1 100644
--- a/src/pkg/gob/encode.go
+++ b/src/pkg/gob/encode.go
@@ -335,11 +335,11 @@
 	valueKind("x"): encString,
 }
 
-func getEncEngine(rt reflect.Type) *encEngine
+func getEncEngine(rt reflect.Type) (*encEngine, os.Error)
 
 // Return the encoding op for the base type under rt and
 // the indirection count to reach it.
-func encOpFor(rt reflect.Type) (encOp, int) {
+func encOpFor(rt reflect.Type) (encOp, int, os.Error) {
 	typ, indir := indirect(rt);
 	op, ok := encOpMap[reflect.Typeof(typ)];
 	if !ok {
@@ -352,7 +352,10 @@
 				break;
 			}
 			// Slices have a header; we decode it to find the underlying array.
-			elemOp, indir := encOpFor(t.Elem());
+			elemOp, indir, err := encOpFor(t.Elem());
+			if err != nil {
+				return nil, 0, err
+			}
 			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
 				slice := (*reflect.SliceHeader)(p);
 				if slice.Len == 0 {
@@ -363,15 +366,21 @@
 			};
 		case *reflect.ArrayType:
 			// True arrays have size in the type.
-			elemOp, indir := encOpFor(t.Elem());
+			elemOp, indir, err := encOpFor(t.Elem());
+			if err != nil {
+				return nil, 0, err
+			}
 			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
 				state.update(i);
 				state.err = encodeArray(state.b, uintptr(p), elemOp, t.Elem().Size(), t.Len(), indir);
 			};
 		case *reflect.StructType:
 			// Generate a closure that calls out to the engine for the nested type.
-			engine := getEncEngine(typ);
-			info := getTypeInfo(typ);
+			engine, err := getEncEngine(typ);
+			if err != nil {
+				return nil, 0, err
+			}
+			info := getTypeInfoNoError(typ);
 			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
 				state.update(i);
 				// indirect through info to delay evaluation for recursive structs
@@ -380,13 +389,13 @@
 		}
 	}
 	if op == nil {
-		panicln("can't happen: encode type", rt.String());
+		return op, indir, os.ErrorString("gob enc: can't happen: encode type" + rt.String());
 	}
-	return op, indir
+	return op, indir, nil
 }
 
 // The local Type was compiled from the actual value, so we know it's compatible.
-func compileEnc(rt reflect.Type) *encEngine {
+func compileEnc(rt reflect.Type) (*encEngine, os.Error) {
 	srt, ok := rt.(*reflect.StructType);
 	if !ok {
 		panicln("can't happen: non-struct");
@@ -395,23 +404,29 @@
 	engine.instr = make([]encInstr, srt.NumField()+1);	// +1 for terminator
 	for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ {
 		f := srt.Field(fieldnum);
-		op, indir := encOpFor(f.Type);
+		op, indir, err := encOpFor(f.Type);
+		if err != nil {
+			return nil, err
+		}
 		engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)};
 	}
 	engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0};
-	return engine;
+	return engine, nil;
 }
 
 // typeLock must be held (or we're in initialization and guaranteed single-threaded).
 // The reflection type must have all its indirections processed out.
-func getEncEngine(rt reflect.Type) *encEngine {
-	info := getTypeInfo(rt);
+func getEncEngine(rt reflect.Type) (*encEngine, os.Error) {
+	info, err := getTypeInfo(rt);
+	if err != nil {
+		return nil, err
+	}
 	if info.encoder == nil {
 		// mark this engine as underway before compiling to handle recursive types.
 		info.encoder = new(encEngine);
-		info.encoder = compileEnc(rt);
+		info.encoder, err = compileEnc(rt);
 	}
-	return info.encoder;
+	return info.encoder, err;
 }
 
 func encode(b *bytes.Buffer, e interface{}) os.Error {
@@ -425,7 +440,10 @@
 		return os.ErrorString("gob: encode can't handle " + v.Type().String())
 	}
 	typeLock.Lock();
-	engine := getEncEngine(rt);
+	engine, err := getEncEngine(rt);
 	typeLock.Unlock();
+	if err != nil {
+		return err
+	}
 	return encodeStruct(engine, b, v.Addr());
 }