regfree(&n4);
regfree(&n5);
p1 = gbranch(optoas(OGT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
}
gcmp(optoas(OCMP, types[TUINT32]), &n2, &n4);
regfree(&n4);
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
}
EXTERN Node* newproc;
EXTERN Node* deferproc;
EXTERN Node* deferreturn;
-EXTERN Node* throwindex;
-EXTERN Node* throwslice;
+EXTERN Node* panicindex;
+EXTERN Node* panicslice;
EXTERN Node* throwreturn;
EXTERN long unmappedzero;
EXTERN int maxstksize;
newproc = sysfunc("newproc");
deferproc = sysfunc("deferproc");
deferreturn = sysfunc("deferreturn");
- throwindex = sysfunc("throwindex");
- throwslice = sysfunc("throwslice");
+ panicindex = sysfunc("panicindex");
+ panicslice = sysfunc("panicslice");
throwreturn = sysfunc("throwreturn");
}
afunclit(&p->to);
break;
- // TODO(kaib): unify newproc and defer if you can figure out how not to break things
case 1: // call in new proc (go)
+ case 2: // deferred call (defer)
regalloc(&r, types[tptr], N);
p = gins(AMOVW, N, &r);
p->from.type = D_OREG;
p->to.offset = 4;
regfree(&r);
- ginscall(newproc, 0);
-
- regalloc(&r, types[tptr], N);
- p = gins(AMOVW, N, &r);
- p->from.type = D_OREG;
- p->from.reg = REGSP;
- p->from.offset = 0;
-
- p = gins(AMOVW, &r, N);
- p->to.type = D_OREG;
- p->to.reg = REGSP;
- p->to.offset = 12;
- p->scond |= C_WBIT;
- regfree(&r);
-
- break;
+ if(proc == 1)
+ ginscall(newproc, 0);
+ else
+ ginscall(deferproc, 0);
- case 2: // deferred call (defer)
- regalloc(&r, types[tptr], N);
- p = gins(AMOVW, N, &r);
- p->from.type = D_OREG;
+ nodreg(&r, types[tptr], 1);
+ p = gins(AMOVW, N, N);
+ p->from.type = D_CONST;
p->from.reg = REGSP;
-
- p = gins(AMOVW, &r, N);
- p->to.type = D_OREG;
+ p->from.offset = 12;
p->to.reg = REGSP;
- p->to.offset = -8;
- p->scond |= C_WBIT;
+ p->to.type = D_REG;
- memset(&n1, 0, sizeof n1);
- n1.op = OADDR;
- n1.left = f;
- gins(AMOVW, &n1, &r);
-
- p = gins(AMOVW, &r, N);
- p->to.type = D_OREG;
- p->to.reg = REGSP;
- p->to.offset = 8;
-
- nodconst(&con, types[TINT32], argsize(f->type));
- gins(AMOVW, &con, &r);
- p = gins(AMOVW, &r, N);
- p->to.type = D_OREG;
- p->to.reg = REGSP;
- p->to.offset = 4;
- regfree(&r);
-
- ginscall(deferproc, 0);
-
- nodreg(&r, types[tptr], D_R1);
- p = gins(AMOVW, N, &r);
- p->from.type = D_OREG;
- p->from.reg = REGSP;
- p->from.offset = 0;
-
- p = gins(AMOVW, &r, N);
- p->to.type = D_OREG;
- p->to.reg = REGSP;
- p->to.offset = 8;
- p->scond |= C_WBIT;
-
if(proc == 2) {
nodconst(&con, types[TINT32], 0);
- nodreg(&r, types[tptr], D_R0);
- gins(ACMP, &con, &r);
+ p = gins(ACMP, &con, N);
+ p->reg = 0;
patch(gbranch(ABNE, T), pret);
}
break;
if(cl > cr) {
if(throwpc == nil) {
throwpc = pc;
- ginscall(throwslice, 0);
+ ginscall(panicslice, 0);
} else
patch(gbranch(AB, T), throwpc);
}
if(throwpc == nil) {
p1 = gbranch(optoas(op, types[TUINT32]), T);
throwpc = pc;
- ginscall(throwslice, 0);
+ ginscall(panicslice, 0);
patch(p1, pc);
} else {
op = brcom(op);
gcmp(optoas(OCMP, types[TUINT32]), reg1, &n3);
regfree(&n3);
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
}
regfree(&n4);
regfree(&n3);
p1 = gbranch(optoas(OGT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
}
nodconst(&n2, types[TUINT64], v);
gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
p1 = gbranch(optoas(OGT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
}
nodconst(&n1, types[TUINT64], nl->type->bound);
gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
}
EXTERN Node* newproc;
EXTERN Node* deferproc;
EXTERN Node* deferreturn;
-EXTERN Node* throwindex;
-EXTERN Node* throwslice;
+EXTERN Node* panicindex;
+EXTERN Node* panicslice;
EXTERN Node* throwreturn;
EXTERN vlong unmappedzero;
newproc = sysfunc("newproc");
deferproc = sysfunc("deferproc");
deferreturn = sysfunc("deferreturn");
- throwindex = sysfunc("throwindex");
- throwslice = sysfunc("throwslice");
+ panicindex = sysfunc("panicindex");
+ panicslice = sysfunc("panicslice");
throwreturn = sysfunc("throwreturn");
}
if(cl > cr) {
if(throwpc == nil) {
throwpc = pc;
- ginscall(throwslice, 0);
+ ginscall(panicslice, 0);
} else
patch(gbranch(AJMP, T), throwpc);
}
if(throwpc == nil) {
p1 = gbranch(optoas(op, types[TUINT32]), T);
throwpc = pc;
- ginscall(throwslice, 0);
+ ginscall(panicslice, 0);
patch(p1, pc);
} else {
op = brcom(op);
}
gins(optoas(OCMP, types[TUINT32]), reg1, &n2);
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
}
nodconst(&n2, types[TUINT64], v);
gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
p1 = gbranch(optoas(OGT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
}
p1 = gins(optoas(OCMP, types[TUINT32]), N, &n2);
p1->from = *a;
p1 = gbranch(optoas(OGT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
a->offset -= Array_nel;
}
int i;
if(symlist[0] == S) {
- symlist[0] = pkglookup("throwindex", runtimepkg);
- symlist[1] = pkglookup("throwslice", runtimepkg);
+ symlist[0] = pkglookup("panicindex", runtimepkg);
+ symlist[1] = pkglookup("panicslice", runtimepkg);
symlist[2] = pkglookup("throwinit", runtimepkg);
- symlist[3] = pkglookup("panicl", runtimepkg);
+ symlist[3] = pkglookup("panic", runtimepkg);
}
s = p->to.sym;
nodconst(&n2, types[TUINT32], v);
gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
p1 = gbranch(optoas(OGT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
}
nodconst(&n1, types[TUINT32], nl->type->bound);
gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
- ginscall(throwindex, 0);
+ ginscall(panicindex, 0);
patch(p1, pc);
}
EXTERN Node* newproc;
EXTERN Node* deferproc;
EXTERN Node* deferreturn;
-EXTERN Node* throwindex;
-EXTERN Node* throwslice;
+EXTERN Node* panicindex;
+EXTERN Node* panicslice;
EXTERN Node* throwreturn;
EXTERN int maxstksize;
extern uint32 unmappedzero;
newproc = sysfunc("newproc");
deferproc = sysfunc("deferproc");
deferreturn = sysfunc("deferreturn");
- throwindex = sysfunc("throwindex");
- throwslice = sysfunc("throwslice");
+ panicindex = sysfunc("panicindex");
+ panicslice = sysfunc("panicslice");
throwreturn = sysfunc("throwreturn");
}
if(cl > cr) {
if(throwpc == nil) {
throwpc = pc;
- ginscall(throwslice, 0);
+ ginscall(panicslice, 0);
} else
patch(gbranch(AJMP, T), throwpc);
}
if(throwpc == nil) {
p1 = gbranch(optoas(op, types[TUINT32]), T);
throwpc = pc;
- ginscall(throwslice, 0);
+ ginscall(panicslice, 0);
patch(p1, pc);
} else {
op = brcom(op);
int i;
if(symlist[0] == S) {
- symlist[0] = pkglookup("throwindex", runtimepkg);
- symlist[1] = pkglookup("throwslice", runtimepkg);
+ symlist[0] = pkglookup("panicindex", runtimepkg);
+ symlist[1] = pkglookup("panicslice", runtimepkg);
symlist[2] = pkglookup("throwinit", runtimepkg);
- symlist[3] = pkglookup("panicl", runtimepkg);
+ symlist[3] = pkglookup("panic", runtimepkg);
}
s = p->to.sym;
}
if(epc - pc == 5) {
- // check for CALL sys.throwindex
+ // check for CALL sys.panicindex
buf[0] = 0;
machdata->das(text, pc, 0, buf, sizeof buf);
- if(strstr(buf, "throwindex"))
+ if(strstr(buf, "panicindex"))
return;
}
char *runtimeimport =
"package runtime\n"
"func \"\".mal (? int32) *any\n"
- "func \"\".throwindex ()\n"
+ "func \"\".panicindex ()\n"
+ "func \"\".panicslice ()\n"
"func \"\".throwreturn ()\n"
"func \"\".throwinit ()\n"
"func \"\".panic (? interface { })\n"
case ODOTTYPE:
exprfmt(f, n->left, 7);
fmtprint(f, ".(");
- exprfmt(f, n->right, 0);
+ if(n->right != N)
+ exprfmt(f, n->right, 0);
+ else
+ fmtprint(f, "%T", n->type);
fmtprint(f, ")");
break;
// emitted by compiler, not referred to by go programs
func mal(int32) *any
-func throwindex()
+func panicindex()
+func panicslice()
func throwreturn()
func throwinit()
if(defer) {
if(op == OPRINTN)
fmtprint(&fmt, "\n");
- if(op == OPANIC)
- fmtprint(&fmt, "%%!");
on = syslook("printf", 1);
on->type = functype(nil, intypes, nil);
args->n = nod(OLITERAL, N, N);
typechecklist(calls, Etop);
walkexprlist(calls, init);
- if(op == OPANIC)
- r = mkcall("panicl", T, nil);
- else
- r = nod(OEMPTY, N, N);
+ r = nod(OEMPTY, N, N);
typecheck(&r, Etop);
walkexpr(&r, init);
r->ninit = calls;
b = -b;
if(a <= b) {
if(b == 0)
- throw("complex divide");
+ panicstring("complex divide by zero");
ratio = denreal/denimag;
denom = denreal*ratio + denimag;
quoreal = (numreal*ratio + numimag) / denom;
// The Error interface identifies a run time error.
type Error interface {
String() string
- RuntimeError() // no-op that uniquely identifies runtime.Error
+
+ // RuntimeError is a no-op function but
+ // serves to distinguish types that are runtime
+ // errors from ordinary os.Errors: a type is a
+ // runtime error if it has a RuntimeError method.
+ RuntimeError()
}
// A TypeAssertionError explains a failed type assertion.
missingMethod string // one method needed by Interface, missing from Concrete
}
+func (*TypeAssertionError) RuntimeError() {}
+
func (e *TypeAssertionError) String() string {
inter := e.interfaceString
if inter == "" {
return e.missingMethod
}
-func (*TypeAssertionError) RuntimeError() {}
-
// For calling from C.
func newTypeAssertionError(pt1, pt2, pt3 *Type, ps1, ps2, ps3 *string, pmeth *string, ret *interface{}) {
var t1, t2, t3 Type
*ret = &TypeAssertionError{t1, t2, t3, s1, s2, s3, meth}
}
+// An errorString represents a runtime error described by a single string.
+type errorString string
+
+func (e errorString) RuntimeError() {}
+
+func (e errorString) String() string {
+ return "runtime error: " + string(e)
+}
+
+// For calling from C.
+func newErrorString(s string, ret *interface{}) {
+ *ret = errorString(s)
+}
+
type stringer interface {
String() string
}
// For calling from C.
-// Prints an argument to panic.
+// Prints an argument passed to panic.
// There's room for arbitrary complexity here, but we keep it
// simple and handle just a few important cases: int, string, and Stringer.
func printany(i interface{}) {
mapaccess(h, ak, av, &pres);
-// new spec -- all elements have "zero" value
-// if(!pres)
-// throw("runtime.mapaccess1: key not in map");
-
if(debug) {
prints("runtime.mapaccess1: map=");
·printpointer(h);
ifacehash1(void *data, Type *t)
{
int32 alg, wid;
+ Eface err;
if(t == nil)
return 0;
alg = t->alg;
wid = t->size;
if(algarray[alg].hash == nohash) {
- // calling nohash will throw too,
+ // calling nohash will panic too,
// but we can print a better error.
- printf("hash of unhashable type %S\n", *t->string);
- if(alg == AFAKE)
- throw("fake interface hash");
- throw("interface hash");
+ ·newErrorString(catstring(gostring((byte*)"hash of unhashable type "), *t->string), &err);
+ ·panic(err);
}
if(wid <= sizeof(data))
return algarray[alg].hash(wid, &data);
ifaceeq1(void *data1, void *data2, Type *t)
{
int32 alg, wid;
+ Eface err;
alg = t->alg;
wid = t->size;
if(algarray[alg].equal == noequal) {
- // calling noequal will throw too,
+ // calling noequal will panic too,
// but we can print a better error.
- printf("comparing uncomparable type %S\n", *t->string);
- if(alg == AFAKE)
- throw("fake interface compare");
- throw("interface compare");
+ ·newErrorString(catstring(gostring((byte*)"comparing uncomparable type "), *t->string), &err);
+ ·panic(err);
}
if(wid <= sizeof(data1))
}
void
-·throwindex(void)
+·panicindex(void)
{
- throw("index out of range");
+ panicstring("index out of range");
}
void
-·throwslice(void)
+·panicslice(void)
{
- throw("slice out of range");
+ panicstring("slice bounds out of range");
}
void
·throwreturn(void)
{
- throw("no return at end of a typed function");
+ // can only happen if compiler is broken
+ throw("no return at end of a typed function - compiler is broken");
}
void
·throwinit(void)
{
- throw("recursive call during initialization");
+ // can only happen with linker skew
+ throw("recursive call during initialization - linker skew");
}
void
exit(1); // even more not reached
}
+void
+panicstring(int8 *s)
+{
+ Eface err;
+
+ ·newErrorString(gostring((byte*)s), &err);
+ ·panic(err);
+}
+
void
mcpy(byte *t, byte *f, uint32 n)
{
{
USED(s);
USED(a);
- throw("hash of unhashable type");
+ panicstring("hash of unhashable type");
return 0;
}
USED(s);
USED(a);
USED(b);
- throw("comparing uncomparable types");
+ panicstring("comparing uncomparable types");
return 0;
}
-static void
-noprint(uint32 s, void *a)
-{
- USED(s);
- USED(a);
- throw("print of unprintable type");
-}
-
-static void
-nocopy(uint32 s, void *a, void *b)
-{
- USED(s);
- USED(a);
- USED(b);
- throw("copy of uncopyable type");
-}
-
Alg
algarray[] =
{
[ASTRING] { strhash, strequal, strprint, memcopy },
[AINTER] { interhash, interequal, interprint, memcopy },
[ANILINTER] { nilinterhash, nilinterequal, nilinterprint, memcopy },
-[AFAKE] { nohash, noequal, noprint, nocopy },
};
#pragma textflag 7
ASTRING,
AINTER,
ANILINTER,
- AFAKE,
Amax
};
void FLUSH(void*);
void* getu(void);
void throw(int8*);
+void panicstring(int8*);
uint32 rnd(uint32, uint32);
void prints(int8*);
void printf(int8*, ...);
void* mal(uintptr);
void* malx(uintptr size, int32 skip_delta);
uint32 cmpstring(String, String);
+String catstring(String, String);
String gostring(byte*);
String gostringw(uint16*);
void initsig(void);
void addfinalizer(void*, void(*fn)(void*), int32);
void walkfintab(void (*fn)(void*));
void runpanic(Panic*);
+void* getcallersp(void*);
void exit(int32);
void breakpoint(void);
void runtime_printcomplex(Complex128);
void reflect·call(byte*, byte*, uint32);
void ·panic(Eface);
-
+void ·panicindex(void);
+void ·panicslice(void);
/*
* runtime c-called (but written in Go)
*/
void ·newError(String, Eface*);
void ·printany(Eface);
void ·newTypeAssertionError(Type*, Type*, Type*, String*, String*, String*, String*, Eface*);
+void ·newErrorString(String, Eface*);
/*
* wrapped for go users
}
}
-static void
-throwslice(uint32 lb, uint32 hb, uint32 n)
-{
- prints("slice[");
- ·printint(lb);
- prints(":");
- ·printint(hb);
- prints("] of [");
- ·printint(n);
- prints("] array\n");
- throw("array slice");
-}
-
// sliceslice(old []any, lb int, hb int, width int) (ary []any);
void
·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
·printint(old.cap);
prints("\n");
}
- throwslice(lb, hb, old.cap);
+ ·panicslice();
}
// new array is inside old array
·printint(old.cap);
prints("\n");
}
- throwslice(lb, old.len, old.cap);
+ ·panicslice();
}
// new array is inside old array
·printint(width);
prints("\n");
}
- throwslice(lb, hb, nel);
+ ·panicslice();
}
// new array is inside old array
return s;
}
-func catstring(s1 String, s2 String) (s3 String) {
- if(s1.len == 0) {
- s3 = s2;
- goto out;
- }
- if(s2.len == 0) {
- s3 = s1;
- goto out;
- }
+String
+catstring(String s1, String s2)
+{
+ String s3;
+
+ if(s1.len == 0)
+ return s2;
+ if(s2.len == 0)
+ return s1;
s3 = gostringsize(s1.len + s2.len);
mcpy(s3.str, s1.str, s1.len);
mcpy(s3.str+s1.len, s2.str, s2.len);
-out:
+ return s3;
}
-static void
-prbounds(int8* s, int32 a, int32 b, int32 c)
-{
- prints(s);
- prints(" ");
- ·printint(a);
- prints("<");
- ·printint(b);
- prints(">");
- ·printint(c);
- prints("\n");
- throw("string bounds");
+
+func catstring(s1 String, s2 String) (s3 String) {
+ s3 = catstring(s1, s2);
}
uint32
if(lindex < 0 || lindex > si.len ||
hindex < lindex || hindex > si.len) {
- ·printpc(&si);
- prints(" ");
- prbounds("slice", lindex, si.len, hindex);
+ ·panicslice();
}
l = hindex-lindex;
int32 l;
if(lindex < 0 || lindex > si.len) {
- ·printpc(&si);
- prints(" ");
- prbounds("slice", lindex, si.len, si.len);
+ ·panicslice();
}
l = si.len-lindex;
func indexstring(s String, i int32) (b byte) {
if(i < 0 || i >= s.len) {
- ·printpc(&s);
- prints(" ");
- prbounds("index", 0, i, s.len);
+ ·panicindex();
}
b = s.str[i];
== ./
=========== ./cmp2.go
-comparing uncomparable type []int
-throw: interface compare
+panic: runtime error: comparing uncomparable type []int
panic PC=xxx
=========== ./cmp3.go
-comparing uncomparable type []int
-throw: interface compare
+panic: runtime error: comparing uncomparable type []int
panic PC=xxx
=========== ./cmp4.go
-hash of unhashable type []int
-throw: interface hash
+panic: runtime error: hash of unhashable type []int
panic PC=xxx
=========== ./cmp5.go
-hash of unhashable type []int
-throw: interface hash
+panic: runtime error: hash of unhashable type []int
panic PC=xxx
}
func die() {
- runtime.Breakpoint() // can't depend on panic
+ runtime.Breakpoint() // can't depend on panic
}
func mustRecover(x interface{}) {
- mustNotRecover() // because it's not a defer call
+ mustNotRecover() // because it's not a defer call
v := recover()
if v == nil {
println("missing recover")
- die() // panic is useless here
+ die() // panic is useless here
}
if v != x {
println("wrong value", v, x)
die()
}
-
+
// the value should be gone now regardless
v = recover()
if v != nil {
func mustNotRecover() {
v := recover()
if v != nil {
- println("spurious recover")
+ println("spurious recover", v)
die()
}
}
func withoutRecover() {
- mustNotRecover() // because it's a sub-call
+ mustNotRecover() // because it's a sub-call
}
func test1() {
- defer mustNotRecover() // because mustRecover will squelch it
- defer mustRecover(1) // because of panic below
- defer withoutRecover() // should be no-op, leaving for mustRecover to find
+ defer mustNotRecover() // because mustRecover will squelch it
+ defer mustRecover(1) // because of panic below
+ defer withoutRecover() // should be no-op, leaving for mustRecover to find
panic(1)
}
// It does not see the panic when called from a call within a deferred call (too late)
// nor does it see the panic when it *is* the deferred call (too early).
defer mustRecover(2)
- defer recover() // should be no-op
+ defer recover() // should be no-op
panic(2)
}
func test3() {
defer mustNotRecover()
defer func() {
- recover() // should squelch
+ recover() // should squelch
}()
panic(3)
}
// Equivalent to test3 but using defer to make the call.
defer mustNotRecover()
defer func() {
- defer recover() // should squelch
+ defer recover() // should squelch
}()
panic(4)
}
println("wrong value", v, 5)
die()
}
-
- s := try(func() { }, "hi").(string)
+
+ s := try(func() {}, "hi").(string)
if s != "hi" {
println("wrong value", s, "hi")
die()
println("try1 wrong value", v, 5)
die()
}
-
- s = try1(func() { }, "hi").(string)
+
+ s = try1(func() {}, "hi").(string)
if s != "hi" {
println("try1 wrong value", s, "hi")
die()
x[0] = 1
x[99999] = 1
_ = x
-
+
v := recover()
if mustRecover {
if v == nil {
--- /dev/null
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2010 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.
+
+// Test of recover for run-time errors.
+
+// TODO(rsc):
+// integer divide by zero?
+// null pointer accesses
+
+package main
+
+import (
+ "os"
+ "strings"
+)
+
+var x = make([]byte, 10)
+
+func main() {
+ test1()
+ test2()
+ test3()
+ test4()
+ test5()
+ test6()
+ test7()
+}
+
+func mustRecover(s string) {
+ v := recover()
+ if v == nil {
+ panic("expected panic")
+ }
+ if e := v.(os.Error).String(); strings.Index(e, s) < 0 {
+ panic("want: " + s + "; have: " + e)
+ }
+}
+
+func test1() {
+ defer mustRecover("index")
+ println(x[123])
+}
+
+func test2() {
+ defer mustRecover("slice")
+ println(x[5:15])
+}
+
+func test3() {
+ defer mustRecover("slice")
+ println(x[11:9])
+}
+
+func test4() {
+ defer mustRecover("interface")
+ var x interface{} = 1
+ println(x.(float))
+}
+
+type T struct {
+ a, b int
+}
+
+func test5() {
+ defer mustRecover("uncomparable")
+ var x T
+ var z interface{} = x
+ println(z != z)
+}
+
+func test6() {
+ defer mustRecover("unhashable")
+ var x T
+ var z interface{} = x
+ m := make(map[interface{}]int)
+ m[z] = 1
+}
+
+func test7() {
+ defer mustRecover("complex divide by zero")
+ var x, y complex
+ println(x / y)
+}