tempfree(&n1);
                return;
        }
-
+       
        // 64-bit ops are hard on 32-bit machine.
        if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) {
                switch(n->op) {
                }
        }
 
-       if(isfloat[n->type->etype] && isfloat[nl->type->etype])
+       if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype])
                goto flt;
 
        switch(n->op) {
 
        // unary
        cgen(nl, &f0);
-       if(n->op != OCONV)
+       if(n->op != OCONV && n->op != OPLUS)
                gins(foptoas(n->op, n->type, 0), &f0, &f0);
        gmove(&f0, res);
        return;
 
        Node *n, *nn;
 
        n = *np;
-       if(n == N || t == T || n->type == T || isideal(t) || eqtype(t, n->type))
+       if(n == N || t == T || n->type == T || isideal(t) || n->type == t)
                return;
        if(!explicit && !isideal(n->type))
                return;
                s = mal(sizeof(*s)+l);
                s->len = l;
                runetochar((char*)s->s, &rune);
+               memset(&v, 0, sizeof v);
                v.ctype = CTSTR;
                v.u.sval = s;
                break;
 
        case CTFLT:
                yyerror("no float -> string");
+       
+       case CTNIL:
+               memset(&v, 0, sizeof v);
+               v.ctype = CTSTR;
+               v.u.sval = mal(sizeof *s);
+               break;
        }
        return v;
 }
                }
                return;
 
+       case TUP(OCONV, CTNIL):
+       case TUP(OARRAYBYTESTR, CTNIL):
+               if(n->type->etype == TSTRING) {
+                       v = tostr(v);
+                       nl->type = n->type;
+                       break;
+               }
+               // fall through
        case TUP(OCONV, CTINT):
        case TUP(OCONV, CTFLT):
        case TUP(OCONV, CTSTR):
-       case TUP(OCONV, CTNIL):
-       case TUP(OARRAYBYTESTR, CTNIL):
                convlit1(&nl, n->type, 1);
                break;
 
        default:
                fatal("nodlit ctype %d", v.ctype);
        case CTSTR:
-               n->type = types[TSTRING];
+               n->type = idealstring;
                break;
        case CTBOOL:
-               n->type = types[TBOOL];
+               n->type = idealbool;
                break;
        case CTINT:
        case CTFLT:
                }
                defaultlit(&n->left, t);
                defaultlit(&n->right, t);
-               n->type = n->left->type;
+               if(n->type == idealbool || n->type == idealstring)
+                       n->type = types[n->type->etype];
+               else
+                       n->type = n->left->type;
                return;
        }
 
                }
                yyerror("defaultlit: unknown literal: %#N", n);
                break;
+       case CTBOOL:
+               n->type = types[TBOOL];
+               break;
        case CTINT:
                n->type = types[TINT];
                if(t != T) {
        r = *rp;
        if(l->type == T || r->type == T)
                return;
-       if(l->type->etype != TIDEAL && l->type->etype != TNIL) {
+       if(!isideal(l->type)) {
                convlit(rp, l->type);
                return;
        }
-       if(r->type->etype != TIDEAL && r->type->etype != TNIL) {
+       if(!isideal(r->type)) {
                convlit(lp, r->type);
                return;
        }
 
 
        Bprint(bout, "\t");
        Bprint(bout, "const %lS", s);
-       if(t != T && t->etype != TIDEAL)
+       if(t != T && !isideal(t))
                Bprint(bout, " %#T", t);
        Bprint(bout, " = ");
 
 
 
        switch(nr->op) {
        case ONAME:
-               gused(nr);
+               if(!(nr->class & PHEAP))
+                       gused(nr);
                break;
 
        // unary
 
 
 EXTERN Type*   types[NTYPE];
 EXTERN Type*   idealstring;
+EXTERN Type*   idealbool;
 EXTERN uchar   simtype[NTYPE];
 EXTERN uchar   isptr[NTYPE];
 EXTERN uchar   isforw[NTYPE];
 
        s->def->iota = 1;
        s->def->sym = s;
 
-       s = pkglookup("true", "/builtin/");
-       s->def = nodbool(1);
-       s->def->sym = lookup("true");
-
-       s = pkglookup("false", "/builtin/");
-       s->def = nodbool(0);
-       s->def->sym = lookup("false");
-
-
        // logically, the type of a string literal.
        // types[TSTRING] is the named type string
        // (the type of x in var x string or var x = "hello").
        // (the type of x in const x = "hello").
        // TODO(rsc): this may need some more thought.
        idealstring = typ(TSTRING);
+       idealbool = typ(TBOOL);
+
+       s = pkglookup("true", "/builtin/");
+       s->def = nodbool(1);
+       s->def->sym = lookup("true");
+       s->def->type = idealbool;
+
+       s = pkglookup("false", "/builtin/");
+       s->def = nodbool(0);
+       s->def->sym = lookup("false");
+       s->def->type = idealbool;
 
        s = lookup("_");
        s->block = -100;
 
        Sym *s;
        Node *n;
 
-       if(isptr[t->etype] && t->type == T)
+       if((isptr[t->etype] && t->type == T) || isideal(t))
                fatal("typename %T", t);
        s = typesym(t);
        if(s->def == N) {
        Type *t1;
        Sym *tsym;
 
-       if(t->etype == TNIL || t->etype == TIDEAL || t == idealstring)
-               fatal("dtypesym ideal %T", t);
+       if(isideal(t))
+               fatal("dtypesym %T", t);
 
        s = typesym(t);
        if(s->flags & SymSiggen)
 
        c = nodintconst(0);
        c->val.ctype = CTBOOL;
        c->val.u.bval = b;
-       c->type = types[TBOOL];
+       c->type = idealbool;
        return c;
 }
 
                return fmtprint(fp, "%S", s);
        }
 
-       if(t->etype < nelem(basicnames) && basicnames[t->etype] != nil)
+       if(t->etype < nelem(basicnames) && basicnames[t->etype] != nil) {
+               if(isideal(t) && t->etype != TIDEAL && t->etype != TNIL)
+                       fmtprint(fp, "ideal ");
                return fmtprint(fp, "%s", basicnames[t->etype]);
+       }
 
        switch(t->etype) {
        case TPTR32:
 {
        if(t == T)
                return 0;
-       if(t == idealstring)
-               return 1;
-       return t->etype == TNIL || t->etype == TIDEAL;
+       return t == idealstring || t == idealbool || t->etype == TNIL || t->etype == TIDEAL;
 }
 
 /*
 
                                        if(ll->n->op == OTYPE)
                                                yyerror("type %T is not an expression", ll->n->type);
                                        else if(ll->n->type != T && !eqtype(ll->n->type, t))
-                                               yyerror("case %+N in switch of %+N %#O", ll->n, n->ntest, ll->n->op);
+                                               yyerror("case %+N in %T switch", ll->n, t);
                                        break;
                                case Etype:     // type switch
                                        if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL))
 
                        goto badbinary;
                t = l->type;
                if(iscmp[n->op]) {
-                       t = types[TBOOL];
+                       t = idealbool;
                        evconst(n);
                        if(n->op != OLITERAL) {
                                defaultlit2(&l, &r, 1);
                        goto error;
                // TODO: more aggressive
                n->etype = 0;
-               if(top & Erv)
+               n->type = T;
+               if(top & Erv) {
                        n->op = OSENDNB;
-               n->type = types[TBOOL];
+                       n->type = idealbool;
+               }
                goto ret;
 
        case OSLICE:
                        goto error;
                }
                if(n->op == OCLOSED) {
-                       n->type = types[TBOOL];
+                       n->type = idealbool;
                        ok |= Erv;
                } else
                        ok |= Etop;
        return 1;
 }
 
+/*
+ * check implicit or explicit conversion from node type nt to type t.
+ */
 int
 checkconv(Type *nt, Type *t, int explicit, int *op, int *et)
 {
        *op = OCONV;
        *et = 0;
 
+       
+
        // preexisting error
        if(t == T || t->etype == TFORW)
                return 0;
        // accept anything involving interfaces and let ifacecvt
        // generate a good message.  some messages have to be
        // delayed anyway.
+       // TODO(rsc): now that everything is delayed for whole-package
+       // compilation, the messages could be generated right here.
        if(isnilinter(t) || isnilinter(nt) || isinter(t) || isinter(nt)) {
                *et = ifaceas1(t, nt, 0);
                *op = OCONVIFACE;
                return n;
 
        if(n->op == OLITERAL)
-       if(explicit || n->type->etype == TIDEAL || n->type == idealstring || n->type->etype == TNIL)
+       if(explicit || isideal(n->type))
        if(cvttype(t, n->type)) {
                // can convert literal in place
                // TODO(rsc) is this needed?
                return n;
        }
 
+       if(op == OCONVIFACE)
+               defaultlit(&n, T);
+
        if(nconv == N)
                nconv = nod(OCONV, n, N);
        nconv->op = op;
                n->op = OAS2MAPW;
                n->rlist->n = typecheckconv(nil, r, l->type->down, 0);
                r = n->rlist->next->n;
-               n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 0);
+               n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 1);
                goto out;
        }
 
                        if(l->defn == n)
                                l->type = r->type;
                        l = n->list->next->n;
-                       if(l->type != T && checkconv(types[TBOOL], l->type, 0, &op, &et) < 0)
+                       if(l->type != T && checkconv(idealbool, l->type, 0, &op, &et) < 0)
                                yyerror("cannot assign bool value to %+N", l);
                        if(l->defn == n && l->ntype == N)
                                l->type = types[TBOOL];
 
                if(n->etype == OANDNOT) {
                        n->etype = OAND;
                        n->right = nod(OCOM, n->right, N);
-                       n->right->type = n->right->left->type;
+                       typecheck(&n->right, Erv);
                        goto ret;
                }
 
                walkexpr(&n->right, init);
                n->op = OAND;
                n->right = nod(OCOM, n->right, N);
-               n->right->type = n->right->left->type;
+               typecheck(&n->right, Erv);
                goto ret;
 
        case ODIV: