Iter save;
        Strlit *note;
        int lno;
+       Node *init;
 
+       init = N;
        lno = lineno;
-       n = listfirst(&save, &n);
-
-loop:
-       note = nil;
-       if(n == N) {
-               *t = T;
-               lineno = lno;
-               return t;
-       }
+       for(n = listfirst(&save, &n); n != N; n = listnext(&save)) {
+               note = nil;
 
-       lineno = n->lineno;
-       if(n->op == OLIST) {
-               // recursive because it can be lists of lists
-               t = stotype(n, et, t);
-               goto next;
-       }
+               lineno = n->lineno;
+               if(n->op == OLIST) {
+                       // recursive because it can be lists of lists
+                       t = stotype(n, et, t);
+                       continue;
+               }
 
-       if(n->op != ODCLFIELD)
-               fatal("stotype: oops %N\n", n);
+               if(n->op != ODCLFIELD)
+                       fatal("stotype: oops %N\n", n);
+               if(n->right != N) {
+                       walkexpr(n->right, Etype, &init);
+                       n->type = n->right->type;
+                       n->right = N;
+                       if(n->embedded && n->type != T) {
+                               t1 = n->type;
+                               if(t1->sym == S && isptr[t1->etype])
+                                       t1 = t1->type;
+                               if(t1 != T && isptr[t1->etype])
+                                       yyerror("embedded type cannot be a pointer");
+                       }
+               }
 
-       if(n->type == T) {
-               // assume error already printed
-               goto next;
-       }
+               if(n->type == T) {
+                       // assume error already printed
+                       continue;
+               }
 
-       switch(n->val.ctype) {
-       case CTSTR:
-               if(et != TSTRUCT)
-                       yyerror("interface method cannot have annotation");
-               note = n->val.u.sval;
-               break;
-       default:
-               if(et != TSTRUCT)
-                       yyerror("interface method cannot have annotation");
-               else
-                       yyerror("field annotation must be string");
-       case CTxxx:
-               note = nil;
-               break;
-       }
+               switch(n->val.ctype) {
+               case CTSTR:
+                       if(et != TSTRUCT)
+                               yyerror("interface method cannot have annotation");
+                       note = n->val.u.sval;
+                       break;
+               default:
+                       if(et != TSTRUCT)
+                               yyerror("interface method cannot have annotation");
+                       else
+                               yyerror("field annotation must be string");
+               case CTxxx:
+                       note = nil;
+                       break;
+               }
 
-       if(et == TINTER && n->left == N) {
-               // embedded interface - inline the methods
-               if(n->type->etype != TINTER) {
-                       yyerror("interface contains embedded non-interface %T", t);
-                       goto next;
+               if(et == TINTER && n->left == N) {
+                       // embedded interface - inline the methods
+                       if(n->type->etype != TINTER) {
+                               yyerror("interface contains embedded non-interface %T", t);
+                               continue;
+                       }
+                       for(t1=n->type->type; t1!=T; t1=t1->down) {
+                               // TODO(rsc): Is this really an error?
+                               if(strcmp(t1->sym->package, package) != 0)
+                                       yyerror("embedded interface contains unexported method %S", t1->sym);
+                               f = typ(TFIELD);
+                               f->type = t1->type;
+                               f->width = BADWIDTH;
+                               f->nname = newname(t1->sym);
+                               f->sym = t1->sym;
+                               *t = f;
+                               t = &f->down;
+                       }
+                       continue;
                }
-               for(t1=n->type->type; t1!=T; t1=t1->down) {
-                       if(strcmp(t1->sym->package, package) != 0)
-                               yyerror("embedded interface contains unexported method %S", t1->sym);
-                       f = typ(TFIELD);
-                       f->type = t1->type;
-                       f->width = BADWIDTH;
-                       f->nname = newname(t1->sym);
-                       f->sym = t1->sym;
-                       *t = f;
-                       t = &f->down;
+
+               f = typ(TFIELD);
+               f->type = n->type;
+               f->note = note;
+               f->width = BADWIDTH;
+
+               if(n->left != N && n->left->op == ONAME) {
+                       f->nname = n->left;
+                       f->embedded = n->embedded;
+                       f->sym = f->nname->sym;
+                       if(pkgimportname != S && !exportname(f->sym->name))
+                               f->sym = pkglookup(f->sym->name, structpkg);
                }
-               goto next;
-       }
 
-       f = typ(TFIELD);
-       f->type = n->type;
-       f->note = note;
-       f->width = BADWIDTH;
-
-       if(n->left != N && n->left->op == ONAME) {
-               f->nname = n->left;
-               f->embedded = n->embedded;
-               f->sym = f->nname->sym;
-               if(pkgimportname != S && !exportname(f->sym->name))
-                       f->sym = pkglookup(f->sym->name, structpkg);
+               *t = f;
+               t = &f->down;
        }
 
-       *t = f;
-       t = &f->down;
-
-next:
-       n = listnext(&save);
-       goto loop;
+       *t = T;
+       lineno = lno;
+       return t;
 }
 
 Type*
        if(s == S)
                return T;
        if(s->def == N || s->def->op != OTYPE) {
-               yyerror("%S is not a type", s);
+               if(!s->undef)
+                       yyerror("%S is not a type", s);
                return T;
        }
        t = s->def->type;
        n->embedded = 1;
        if(s == S)
                return n;
-       n->type = oldtype(s);
-       if(n->type != T && isptr[n->type->etype])
-               yyerror("embedded type cannot be a pointer");
+       n->right = oldname(s);
        return n;
 }
 
 
        // OLITERAL/OREGISTER
        Val     val;
 
+       // OTFUNC
+       Node*   rcvr;
+
        // ONAME func param with PHEAP
        Node*   heapaddr;       // temp holding heap address of param
        Node*   stackparam;     // OPARAM node referring to stack copy of param
        ODOTTYPE, OTYPESW,
        OBAD,
 
+       OTCHAN, OTMAP, OTSTRUCT, OTINTER, OTFUNC, OTARRAY,
+
        OEXTEND,        // 6g internal
 
        OEND,
        Etop,           // evaluated at statement level
        Elv,            // evaluated in lvalue context
        Erv,            // evaluated in rvalue context
+       Etype = 1<<8,
 };
 
 #define        BITS    5
 uint32 stringhash(char*);
 Sym*   lookup(char*);
 Sym*   pkglookup(char*, char*);
-Sym*   opkglookup(char*, char*);
+Sym*   restrictlookup(char*, char*);
 void   importdot(Sym*);
 void   yyerror(char*, ...);
 void   warn(char*, ...);
 void   walkstmt(Node*);
 void   walkexpr(Node*, int, Node**);
 void   walkconv(Node*, Node**);
+void   walkdottype(Node*, Node**);
 void   walkas(Node*);
 void   walkbool(Node*);
 void   walkswitch(Node*);
 
 %type  <sym>   sym packname
 %type  <val>   oliteral
 
-%type  <node>  stmt
+%type  <node>  stmt ntype
 %type  <node>  arg_type arg_type_list
 %type  <node>  arg_type_list_r braced_keyexpr_list case caseblock
 %type  <node>  caseblock_list_r common_dcl
 %type  <node>  switch_body switch_stmt uexpr vardcl vardcl_list_r
 %type  <node>  xdcl xdcl_list_r xfndcl
 
-%type  <type>  convtype dotdotdot
-%type  <type>  fnlitdcl fntype indcl interfacetype
-%type  <type>  new_type structtype type typedclname
-%type  <type>  chantype non_chan_type othertype non_fn_type
+%type  <type>  type
+%type  <node>  convtype dotdotdot
+%type  <node>  indcl interfacetype structtype
+%type  <type>  new_type typedclname fnlitdcl fntype
+%type  <node>  chantype non_chan_type othertype non_fn_type
 
 %type  <sym>   hidden_importsym hidden_pkg_importsym
 
                                $$ = nod(OXCASE, $$, N);
                                break;
                        }
+                       e = nerrors;
+                       walkexpr($2, Etype | Erv, &top);
                        if($2->op == OTYPE) {
                                $$ = old2new(typeswvar->right, $2->type, &top);
                                $$ = nod(OTYPESW, $$, N);
                                $$->ninit = top;
                                break;
                        }
-                       e = nerrors;
-                       gettype($2, nil);
-                       // maybe gettype found problems that keep
+                       // maybe walkexpr found problems that keep
                        // e from being valid even outside a type switch.
-                       // only complain if gettype didn't print new errors.
+                       // only complain if walkexpr didn't print new errors.
                        if(nerrors == e)
                                yyerror("non-type case in type switch");
                        $$ = nod(OXCASE, N, N);
        pexpr
 |      '*' uexpr
        {
-               if($2->op == OTYPE) {
-                       $$ = typenod(ptrto($2->type));
-                       break;
-               }
                $$ = nod(OIND, $2, N);
        }
 |      '&' uexpr
                $$ = unsafenmagic($1, $3);
                if($$)
                        break;
-               if($1->op == OTYPE) {
-                       // type conversion
-                       if($3 == N)
-                               yyerror("conversion to %T missing expr", $1->type);
-                       else if($3->op == OLIST)
-                               yyerror("conversion to %T has too many exprs", $1->type);
-                       $$ = nod(OCONV, $3, N);
-                       $$->type = $1->type;
-                       break;
-               }
-               if($1->op == ONAME && $1->etype != 0) { // builtin OLEN, OCAP, etc
-                       $$ = nod($1->etype, $3, N);
-                       break;
-               }
                $$ = nod(OCALL, $1, $3);
        }
 
        {
                if($1->op == OPACK) {
                        Sym *s;
-                       s = pkglookup($3->name, $1->sym->name);
+                       s = restrictlookup($3->name, $1->sym->name);
                        $$ = oldname(s);
                        break;
                }
        }
 |      pexpr '.' '(' expr_or_type ')'
        {
-               $$ = nod(ODOTTYPE, $1, N);
-               if($4->op != OTYPE)
-                       yyerror("expected type got %O", $4->op);
-               $$->type = $4->type;
+               $$ = nod(ODOTTYPE, $1, $4);
        }
 |      pexpr '.' '(' LTYPE ')'
        {
 |      convtype '(' expr ')'
        {
                // conversion
-               $$ = nod(OCONV, $3, N);
-               $$->type = $1;
+               $$ = nod(OCALL, $1, $3);
        }
 |      convtype lbrace braced_keyexpr_list '}'
        {
                $$ = rev($3);
                if($$ == N)
                        $$ = nod(OEMPTY, N, N);
-               $$ = nod(OCOMPOS, $$, N);
-               $$->type = $1;
+               $$ = nod(OCOMPOS, $$, $1);
 
                // If the opening brace was an LBODY,
                // set up for another one now that we're done.
                $$ = rev($3);
                if($$ == N)
                        $$ = nod(OEMPTY, N, N);
-               $$ = nod(OCOMPOS, $$, N);
-               if($1->op != OTYPE)
-                       yyerror("expected type in composite literal");
-               else
-                       $$->type = $1->type;
+               $$ = nod(OCOMPOS, $$, $1);
        }
 |      fnliteral
 
 expr_or_type:
        expr
-|      type    %prec PreferToRightParen
-       {
-               $$ = typenod($1);
-       }
+|      ntype   %prec PreferToRightParen
 
 name_or_type:
        dotname
        name
 
 convtype:
-       '[' oexpr ']' type
+       '[' oexpr ']' ntype
        {
                // array literal
-               $$ = aindex($2, $4);
+               $$ = nod(OTARRAY, $2, $4);
        }
-|      '[' LDDD ']' type
+|      '[' dotdotdot ']' ntype
        {
                // array literal of nelem
-               $$ = aindex(N, $4);
-               $$->bound = -100;
+               $$ = nod(OTARRAY, $2, $4);
        }
-|      LMAP '[' type ']' type
+|      LMAP '[' ntype ']' ntype
        {
                // map literal
-               $$ = maptype($3, $5);
+               $$ = nod(OTMAP, $3, $5);
        }
 |      structtype
 
 dotdotdot:
        LDDD
        {
-               $$ = typ(TDDD);
+               $$ = typenod(typ(TDDD));
        }
 
 type:
+       ntype
+       {
+               Node *init;
+
+               init = N;
+               walkexpr($1, Etype, &init);
+               // init can only be set if this was not a type; ignore
+
+               $$ = $1->type;
+       }
+
+ntype:
        chantype
-|      fntype
+|      fntype { $$ = typenod($1); }
 |      othertype
-|      '(' type ')'
+|      '(' ntype ')'
        {
                $$ = $2;
        }
 
 non_chan_type:
-       fntype
+       fntype { $$ = typenod($1); }
 |      othertype
-|      '(' type ')'
+|      '(' ntype ')'
        {
                $$ = $2;
        }
        {
                if($1->op == OPACK) {
                        Sym *s;
-                       s = pkglookup($3->name, $1->sym->name);
+                       s = restrictlookup($3->name, $1->sym->name);
                        $$ = oldname(s);
                        break;
                }
 othertype:
        '[' oexpr ']' type
        {
-               $$ = aindex($2, $4);
+               $$ = typenod(aindex($2, $4));
        }
-|      LCOMM LCHAN type
+|      LCOMM LCHAN ntype
        {
-               $$ = typ(TCHAN);
-               $$->type = $3;
-               $$->chan = Crecv;
+               $$ = nod(OTCHAN, $3, N);
+               $$->etype = Crecv;
        }
 |      LCHAN LCOMM non_chan_type
        {
-               $$ = typ(TCHAN);
-               $$->type = $3;
-               $$->chan = Csend;
+               $$ = nod(OTCHAN, $3, N);
+               $$->etype = Csend;
        }
-|      LMAP '[' type ']' type
+|      LMAP '[' ntype ']' ntype
        {
-               $$ = maptype($3, $5);
+               $$ = nod(OTMAP, $3, $5);
        }
-|      '*' type
+|      '*' ntype
        {
-               $$ = ptrto($2);
+               $$ = nod(OIND, $2, N);
        }
 |      structtype
 |      interfacetype
 |      dotname
-       {
-               if($1->op == ODOT) {
-                       yyerror("%S.%S is not a type", $1->left->sym, $1->right->sym);
-                       $$ = T;
-                       break;
-               }
-               $$ = oldtype($1->sym);
-       }
 
 chantype:
-       LCHAN type
+       LCHAN ntype
        {
-               $$ = typ(TCHAN);
-               $$->type = $2;
-               $$->chan = Cboth;
+               $$ = nod(OTCHAN, $2, N);
+               $$->etype = Cboth;
        }
 
 structtype:
        LSTRUCT '{' structdcl_list_r osemi '}'
        {
-               $$ = dostruct(rev($3), TSTRUCT);
+               $$ = nod(OTSTRUCT, rev($3), N);
                // Distinguish closing brace in struct from
                // other closing braces by explicitly marking it.
                // Used above (yylast == LSEMIBRACE).
        }
 |      LSTRUCT '{' '}'
        {
-               $$ = dostruct(N, TSTRUCT);
+               $$ = nod(OTSTRUCT, N, N);
                yylast = LSEMIBRACE;
        }
 
 interfacetype:
        LINTERFACE '{' interfacedcl_list_r osemi '}'
        {
-               $$ = dostruct(rev($3), TINTER);
-               $$ = sortinter($$);
+               $$ = nod(OTINTER, rev($3), N);
                yylast = LSEMIBRACE;
        }
 |      LINTERFACE '{' '}'
        {
-               $$ = dostruct(N, TINTER);
+               $$ = nod(OTINTER, N, N);
                yylast = LSEMIBRACE;
        }
 
        }
 |      non_fn_type
        {
-               $$ = nod(ODCLFIELD, N, N);
-               $$->type = $1;
+               $$ = nod(ODCLFIELD, N, $1);
                $$ = cleanidlist($$);
        }
 |      '(' oarg_type_list ')'
                $$ = nod(ODCLFIELD, $1, N);
                $$ = nod(OLIST, $$, $3);
        }
-|      new_field type oliteral
+|      new_field ntype oliteral
        {
-               $$ = nod(ODCLFIELD, $1, N);
-               $$->type = $2;
+               $$ = nod(ODCLFIELD, $1, $2);
                $$->val = $3;
        }
 |      embed oliteral
 |      '*' embed oliteral
        {
                $$ = $2;
-               $$->type = ptrto($$->type);
+               $$->right = nod(OIND, $$->right, N);
                $$->val = $3;
        }
 
                        pkg = $1->name;
                } else
                        pkg = $1->def->sym->name;
-               $$ = pkglookup($3->name, pkg);
+               $$ = restrictlookup($3->name, pkg);
        }
 
 embed:
        }
 |      new_name indcl
        {
-               $$ = nod(ODCLFIELD, $1, N);
-               $$->type = $2;
+               $$ = nod(ODCLFIELD, $1, $2);
        }
 
 interfacedcl:
        interfacedcl1
 |      packname
        {
-               $$ = nod(ODCLFIELD, N, N);
-               $$->type = oldtype($1);
+               $$ = nod(ODCLFIELD, N, typenod(oldtype($1)));
        }
 
 indcl:
        '(' oarg_type_list ')' fnres
        {
                // without func keyword
-               $$ = functype(fakethis(), $2, $4);
+               $$ = typenod(functype(fakethis(), $2, $4));
        }
 
 /*
                        $$ = nod(ONONAME, N, N);
                        $$->sym = $1;
                }
-               $$ = nod(OKEY, $$, typenod($2));
+               $$ = nod(OKEY, $$, $2);
        }
 |      dotdotdot
-       {
-               $$ = typenod($1);
-       }
 
 arg_type_list_r:
        arg_type
 hidden_structdcl:
        sym hidden_type oliteral
        {
-               $$ = nod(ODCLFIELD, newname($1), N);
-               $$->type = $2;
+               $$ = nod(ODCLFIELD, newname($1), typenod($2));
                $$->val = $3;
        }
 |      '?' hidden_type oliteral
        {
                if(isptr[$2->etype]) {
                        $$ = embedded($2->type->sym);
-                       $$->type = ptrto($$->type);
+                       $$->right = nod(OIND, $$->right, N);
                } else
                        $$ = embedded($2->sym);
                $$->val = $3;
 hidden_interfacedcl:
        sym '(' ohidden_funarg_list ')' ohidden_funres
        {
-               $$ = nod(ODCLFIELD, newname($1), N);
-               $$->type = functype(fakethis(), $3, $5);
+               $$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
        }
 
 ohidden_funres:
 
 }
 
 Sym*
-pkglookup(char *p, char *k)
+pkglookup(char *name, char *pkg)
 {
        Sym *s;
        uint32 h;
        int c;
 
-       h = stringhash(p) % NHASH;
-       c = p[0];
+       h = stringhash(name) % NHASH;
+       c = name[0];
        for(s = hash[h]; s != S; s = s->link) {
                if(s->name[0] != c)
                        continue;
-               if(strcmp(s->name, p) == 0)
-                       if(s->package && strcmp(s->package, k) == 0)
+               if(strcmp(s->name, name) == 0)
+                       if(s->package && strcmp(s->package, pkg) == 0)
                                return s;
        }
 
        s = mal(sizeof(*s));
-       s->name = mal(strlen(p)+1);
-       strcpy(s->name, p);
+       s->name = mal(strlen(name)+1);
+       strcpy(s->name, name);
 
        // botch - should probably try to reuse the pkg string
-       s->package = mal(strlen(k)+1);
-       strcpy(s->package, k);
+       s->package = mal(strlen(pkg)+1);
+       strcpy(s->package, pkg);
 
        s->link = hash[h];
        hash[h] = s;
        return s;
 }
 
-// find all the symbols in package opkg
+Sym*
+restrictlookup(char *name, char *pkg)
+{
+       if(!exportname(name) && strcmp(pkg, package) != 0)
+               yyerror("cannot refer to %s.%s", pkg, name);
+       return pkglookup(name, pkg);
+}
+       
+
+// find all the exported symbols in package opkg
 // and make them available in the current package
 void
 importdot(Sym *opkg)
                for(s = hash[h]; s != S; s = s->link) {
                        if(s->package[0] != c)
                                continue;
+                       if(!exportname(s->name))
+                               continue;
                        if(strcmp(s->package, opkg->name) != 0)
                                continue;
                        s1 = lookup(s->name);
        [OSLICE]        = "SLICE",
        [OSUB]          = "SUB",
        [OSWITCH]       = "SWITCH",
+       [OTCHAN]        = "TCHAN",
+       [OTMAP] = "TMAP",
+       [OTSTRUCT]      = "TSTRUCT",
+       [OTINTER]       = "TINTER",
+       [OTFUNC]        = "TFUNC",
+       [OTARRAY]       = "TARRAY",
        [OTYPEOF]       = "TYPEOF",
        [OTYPESW]       = "TYPESW",
        [OTYPE]         = "TYPE",
 {
        Node *last, *n;
 
-       if(na->op != OLIST)
+       if(na->op != OLIST) {
+               if(na->op != ODCLFIELD)
+                       fatal("cleanidlist: %O", na->op);
+               if(na->right == N)
+                       fatal("cleanidlist: no type");
                return na;
+       }
 
        for(last=na; last->op == OLIST; last=last->right)
                ;
-       if(last->op != ODCLFIELD)
-               fatal("cleanidlist: %O", last->op);
-       if(last->type == T)
-               fatal("cleanidlist: no type");
 
        for(n=na; n->op == OLIST; n=n->right) {
-               n->left->type = last->type;
+               n->left->right = last->right;
                n->left->val = last->val;
        }
        return na;
 
        // statement of the function
 
        case OGOTO:
-       case OPANIC:
-       case OPANICN:
        case ORETURN:
                return 0;
+
+       case OCALL:
+               if(n->left->op == ONAME) {
+                       switch(n->left->etype) {
+                       case OPANIC:
+                       case OPANICN:
+                               return 0;
+                       }
+               }
+               break;
        }
 
        // all other statements
        Node *r, *l;
        Type *t;
        Sym *s;
-       int et, cl, cr;
+       int et, cl, cr, typeok;
        int32 lno;
 
        if(n == N)
                return;
        lno = setlineno(n);
+       typeok = top & Etype;
+       top &= ~Etype;
 
 loop:
        if(n == N)
        if(debug['w'] > 1 && top == Etop && n->op != OLIST)
                dump("walk-before", n);
 
+reswitch:
        t = T;
        et = Txxx;
 
                goto ret;
 
        case OTYPE:
-               if(!n->diag) {
-                       n->diag = 1;
-                       yyerror("type %T used as expression", n->type);
+               goto ret;
+
+       case OTARRAY:
+               t = typ(TARRAY);
+               l = n->left;
+               r = n->right;
+               if(l == nil) {
+                       t->bound = -1;
+               } else {
+                       walkexpr(l, Erv | Etype, init);
+                       switch(l->op) {
+                       default:
+                               yyerror("invalid array bound %O", l->op);
+                               break;
+
+                       case OLITERAL:
+                               if(consttype(l) == CTINT) {
+                                       t->bound = mpgetfix(l->val.u.xval);
+                                       if(t->bound < 0) {
+                                               yyerror("array bound must be non-negative");
+                                               t->bound = 1;
+                                       }
+                               }
+                               break;
+
+                       case OTYPE:
+                               if(l->type == T)
+                                       break;
+                               if(l->type->etype != TDDD)
+                                       yyerror("invalid array bound %T", l->type);
+                               t->bound = -100;
+                               break;
+                       }
                }
+               walkexpr(r, Etype, init);
+               t->type = r->type;
+               n->op = OTYPE;
+               n->type = t;
+               goto ret;
+
+       case OTMAP:
+               l = n->left;
+               r = n->right;
+               walkexpr(l, Etype, init);
+               walkexpr(r, Etype, init);
+               n->op = OTYPE;
+               n->type = maptype(l->type, r->type);
+               goto ret;
+
+       case OTCHAN:
+               t = typ(TCHAN);
+               l = n->left;
+               walkexpr(l, Etype, init);
+               t->type = l->type;
+               t->chan = n->etype;
+               n->op = OTYPE;
+               n->type = t;
+               goto ret;
+
+       case OTSTRUCT:
+               n->op = OTYPE;
+               n->type = dostruct(n->left, TSTRUCT);
+               goto ret;
+
+       case OTINTER:
+               n->op = OTYPE;
+               n->type = dostruct(n->left, TINTER);
+               n->type = sortinter(n->type);
                goto ret;
 
        case OLIST:
        case OKEY:
-               walkexpr(n->left, top, init);
+               walkexpr(n->left, top | typeok, init);
                n = n->right;
                goto loop;
 
                s = n->sym;
                if(s->undef == 0) {
                        s->undef = 1;
-                       yyerror("%S: undefined", s);
+                       n->diag = 1;
+                       yyerror("undefined: %S", s);
                        goto ret;
                }
                if(top == Etop)
                if(n->left == N)
                        goto ret;
 
-               walkexpr(n->left, Erv, init);
+               if(n->left->op == ONAME && n->left->etype != 0) {
+                       // builtin OLEN, OCAP, etc.
+                       n->op = n->left->etype;
+                       n->left = n->right;
+                       n->right = N;
+                       goto reswitch;
+               }
+
+               walkexpr(n->left, Erv | Etype, init);
                defaultlit(n->left, T);
 
                t = n->left->type;
                        n->op = OCALLMETH;
                if(n->left->op == ODOTINTER)
                        n->op = OCALLINTER;
+               if(n->left->op == OTYPE) {
+                       n->op = OCONV;
+                       if(top != Erv)
+                               goto nottop;
+                       // turn CALL(type, arg) into CONV(arg) w/ type.
+                       n->type = n->left->type;
+                       n->left = n->right;
+                       n->right = N;
+                       goto reswitch;
+               }
 
                if(t->etype != TFUNC) {
                        yyerror("call of a non-function: %T", t);
                        break;
 
                case ODOTTYPE:
+                       walkdottype(r, init);
                        if(cl == 2 && cr == 1) {
                                // a,b = i.(T)
-                               walkexpr(r->left, Erv, init);
                                if(r->left == N)
                                        break;
                                et = ifaceas1(r->type, r->left->type, 1);
        case OEMPTY:
                goto ret;
 
-       case OCONV:
        case ODOTTYPE:
+               walkdottype(n, init);
+               // fall through
+       case OCONV:
                if(top != Erv)
                        goto nottop;
                walkconv(n, init);
                goto ret;
 
        case OCOMPOS:
-               t = n->type;
+               walkexpr(n->right, Etype, init);
+               t = n->right->type;
+               n->type = t;
                if(t == T)
                        goto ret;
+
                l = n->left;
                if(l == N)
                        goto ret;
                if(top != Erv)
                        goto nottop;
                defaultlit(n->left, T);
-               if(n->left->op == OCOMPOS && n->left->type != T) {
+               if(n->left->op == OCOMPOS) {
+                       walkexpr(n->left->right, Etype, init);
+                       n->left->type = n->left->right->type;
+                       if(n->left->type == T)
+                               goto ret;
+
                        Node *nvar, *nas, *nstar;
 
                        // turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
                        goto nottop;
                if(top == Elv)  // even if n is lvalue, n->left is rvalue
                        top = Erv;
-               walkexpr(n->left, top, init);
-               defaultlit(n->left, T);
                if(n->left == N)
                        goto ret;
+               walkexpr(n->left, top | Etype, init);
+               defaultlit(n->left, T);
+               if(n->left->op == OTYPE) {
+                       n->op = OTYPE;
+                       n->type = ptrto(n->left->type);
+                       goto ret;
+               }
                t = n->left->type;
                if(t == T)
                        goto ret;
                if(top != Erv)
                        goto nottop;
                l = n->left;
+               walkexpr(l, Etype, init);
                if(l == N)
                        yyerror("missing argument to new");
                else if(n->right != N)
                        yyerror("too many arguments to new");
-               else if(l->op != OTYPE)
-                       yyerror("argument to new must be type");
                else if((t = l->type) == T)
                        ;
                else
        if(n->diag)
                goto ret;
        n->diag = 1;
-       switch(top) {
+       switch(top | typeok) {
        default:
-               yyerror("didn't expect %O here", n->op);
+               yyerror("didn't expect %O here [top=%d]", n->op, top);
+               break;
+       case Etype:
+               yyerror("operation %O not allowed in type context", n->op);
                break;
        case Etop:
                yyerror("operation %O not allowed in statement context", n->op);
                yyerror("operation %O not allowed in assignment context", n->op);
                break;
        case Erv:
+       case Erv | Etype:
                yyerror("operation %O not allowed in expression context", n->op);
                break;
        }
        if(debug['w'] && top == Etop && n != N)
                dump("walk", n);
 
+       if(typeok && top == 0) {        // must be type
+               if(n->op != OTYPE) {
+                       if(n->sym) {
+                               if(!n->sym->undef)
+                                       yyerror("%S is not a type", n->sym);
+                       } else {
+                               yyerror("expr %O is not type", n->op);
+                               n->op = OTYPE;  // leads to fewer errors later
+                               n->type = T;
+                       }
+               }
+       }
+       if(!typeok && n->op == OTYPE)
+               yyerror("cannot use type %T as expr", n->type);
+
        ullmancalc(n);
        lineno = lno;
 }
                yyerror("IF and FOR require a boolean type");
 }
 
+void
+walkdottype(Node *n, Node **init)
+{
+       walkexpr(n->left, Erv, init);
+       if(n->left == N)
+               return;
+       defaultlit(n->left, T);
+       if(!isinter(n->left->type))
+               yyerror("type assertion requires interface on left, have %T", n->left->type);
+       if(n->right != N) {
+               walkexpr(n->right, Etype, init);
+               n->type = n->right->type;
+               n->right = N;
+       }
+}
+
 void
 walkconv(Node *n, Node **init)
 {
 
        // if using .(T), interface assertion.
        if(n->op == ODOTTYPE) {
-               defaultlit(l, T);
-               if(!isinter(l->type))
-                       yyerror("type assertion requires interface on left, have %T", l->type);
                et = ifaceas1(t, l->type, 1);
                if(et == I2Isame || et == E2Esame)
                        goto nop;
        if(!lookdot(n, t)) {
                if(!n->diag) {
                        n->diag = 1;
-                       yyerror("undefined DOT %S on %T", n->right->sym, n->left->type);
+                       yyerror("undefined: %T field %S", n->left->type, n->right->sym);
                }
        }
 }
 makecompat(Node *n)
 {
        Type *t;
-       Node *l, *r;
+       Node *l, *r, *init;
 
        l = n->left;
        r = N;
                r = l->right;
                l = l->left;
        }
+       init = N;
+       walkexpr(l, Etype, &init);
        if(l->op != OTYPE) {
                yyerror("cannot make(expr)");
                return n;
        /* check calls early, to give better message for a := f() */
        if(cr == 1) {
                switch(nr->op) {
+               case OCALL:
+                       if(nr->left->op == ONAME && nr->left->etype != 0)
+                               break;
+                       walkexpr(nr->left, Erv | Etype, init);
+                       if(nr->left->op == OTYPE)
+                               break;
+                       goto call;
                case OCALLMETH:
                case OCALLINTER:
-               case OCALL:
                        walkexpr(nr->left, Erv, init);
+               call:
                        convlit(nr->left, types[TFUNC]);
                        t = nr->left->type;
                        if(t == T)
 
        case ODOTTYPE:
                // a,b := i.(T)
+               walkdottype(nr, init);
                if(cl != 2)
                        goto badt;
-               walkexpr(nr->left, Erv, init);
-               if(!isinter(nr->left->type))
-                       goto badt;
                // a,b = iface
                a = mixedoldnew(nl->left, nr->type);
                n = a;
 
        previous declaration at fixedbugs/bug035.go:5
 
 =========== fixedbugs/bug037.go
-fixedbugs/bug037.go:6: vlong: undefined
-fixedbugs/bug037.go:6: s: undefined
+fixedbugs/bug037.go:6: undefined: vlong
+fixedbugs/bug037.go:6: undefined: s
 
 =========== fixedbugs/bug039.go
 fixedbugs/bug039.go:6: variable x redeclared in this block
 broke
 
 =========== fixedbugs/bug072.go
-fixedbugs/bug072.go:6: bug: undefined
+fixedbugs/bug072.go:6: undefined: bug
 
 =========== fixedbugs/bug073.go
 fixedbugs/bug073.go:8: illegal types for operand: LSH
 fixedbugs/bug074.go:6: invalid type for composite literal: string
 
 =========== fixedbugs/bug081.go
-fixedbugs/bug081.go:5: x is not a type
+fixedbugs/bug081.go:5: undefined: x
 
 =========== fixedbugs/bug083.go
-fixedbugs/bug083.dir/bug1.go:9: cannot use type bug0.t0
+fixedbugs/bug083.dir/bug1.go:9: cannot refer to bug0.t0
 
 =========== fixedbugs/bug086.go
 fixedbugs/bug086.go:5: function ends without a return statement
 
 =========== fixedbugs/bug091.go
-fixedbugs/bug091.go:15: c: undefined
+fixedbugs/bug091.go:15: undefined: c
 fixedbugs/bug091.go:15: illegal types for operand: AS
        undefined
 
 
 =========== fixedbugs/bug103.go
 fixedbugs/bug103.go:8: assignment count mismatch: 1 = 0
-fixedbugs/bug103.go:8: x: undefined
+fixedbugs/bug103.go:8: undefined: x
 fixedbugs/bug103.go:8: function requires a return type
 fixedbugs/bug103.go:8: illegal types for operand: AS
        int
        uint64
 
 =========== fixedbugs/bug133.go
-fixedbugs/bug133.dir/bug2.go:11: undefined DOT i on bug0.T
+fixedbugs/bug133.dir/bug2.go:11: undefined: bug0.T field i
 fixedbugs/bug133.dir/bug2.go:11: illegal types for operand: RETURN
        int