case LENGTH: return transformLength(tree);
    public Tree transform(Tree tree, boolean eraseFully) {	assert tree.type != null : tree;	Type owntype = eraseFully ? tree.type.fullErasure() : tree.type.erasure();	switch (tree) {	case ClassDef(int mods, Name name, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl):            Symbol oldCurrentClass = currentClass;            currentClass = tree.symbol();            Tree newTree =                copy.ClassDef(tree, mods, name, new TypeDef[0],                              transform(vparams), tpe, transform(impl, tree.symbol()))		.setType(owntype);            currentClass = oldCurrentClass;            return newTree;	case DefDef(int mods, Name name, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Tree rhs):	    addBridges(tree.symbol());	    Tree tpe1 = gen.mkType(tpe.pos, tpe.type.fullErasure());	    Tree rhs1 = (rhs == Tree.Empty) ? rhs : transform(rhs, tpe1.type);	    return copy.DefDef(		tree, mods, name, new TypeDef[0], transform(vparams), tpe1, rhs1)		.setType(owntype);	case ValDef(int mods, Name name, Tree tpe, Tree rhs):	    Tree tpe1 = transform(tpe);	    Tree rhs1 = (rhs == Tree.Empty) ? rhs : transform(rhs, tpe1.type);	    return copy.ValDef(		tree, mods, name, tpe1, rhs1)		.setType(owntype);	case TypeDef(_, _, _):	    // eliminate	    return Tree.Empty;        case Block(Tree[] stats):            Tree[] newStats = new Tree[stats.length];            for (int i = 0; i < stats.length; ++i)                newStats[i] = transform(stats[i], true);            return copy.Block(tree, newStats).setType(owntype.fullErasure());	case Assign(Tree lhs, Tree rhs):	    Tree lhs1 = transformLhs(lhs);	    Tree rhs1 = transform(rhs, lhs1.type);	    return copy.Assign(tree, lhs1, rhs1).setType(owntype.fullErasure());	case If(Tree cond, Tree thenp, Tree elsep):	    Tree cond1 = transform(cond, Type.unboxedType(TypeTags.BOOLEAN));	    Tree thenp1 = transform(thenp, owntype);	    Tree elsep1 = (elsep == Tree.Empty) ? elsep : transform(elsep, owntype);	    return copy.If(tree, cond1, thenp1, elsep1).setType(owntype);        case New(Template templ):            if (tree.type.symbol() == definitions.UNIT_CLASS)                // !!! return Tree.Literal(UNIT, null).setType(owntype);                throw Debug.abort("found unit literal");            if (tree.type.symbol() == definitions.ARRAY_CLASS) {                switch (templ.parents[0]) {                case Apply(_, Tree[] args):                    args = transform(args);                    switch (owntype) {                    case UnboxedArrayType(Type elemtp):                        switch (elemtp) {                        case UnboxedType(int kind):                            return genNewArray(tree.pos,args[0],kind);                        default:                            return genNewArray(tree.pos,args[0],elemtp);                        }                    default:                        throw Debug.abort("illegal case", owntype);                    }                default:                    throw Debug.abort("illegal case", templ.parents[0]);                }            }	    return super.transform(tree).setType(owntype);	case Typed(Tree expr, Tree tpe):	    // coerce expr to tpe	    Tree tpe1 = gen.mkType(tpe.pos, tpe.type().erasure()); // !!! was transform(tpe);            // !!! More generally, we should never transform a tree            // that represents a type. We should always transform            // types and then reconstruct the corresponding tree.	    return transform(expr, tpe1.type);	case TypeApply(Tree fun, Tree[] args):            Symbol sym = fun.symbol();            if (sym == definitions.AS || sym == definitions.IS) {                Type tp = args[0].type.erasure();                if (isUnboxed(tp)) {                    Tree qual1 = transform(getQualifier(currentClass, fun));                    if (isUnboxed(qual1.type)) qual1 = box(qual1);                    Symbol primSym = (sym == definitions.AS)                        ? primitives.getUnboxValueSymbol(tp)                        : primitives.getInstanceTestSymbol(tp);                    return gen.Select(qual1, primSym);                } else                    return copy.TypeApply(tree, transform(fun), transform(args))                        .setType(owntype);            } else                return transform(fun);	case Apply(Tree fun, Tree[] args):            switch (fun) {            case Select(Tree array, _):                if (isUnboxedArray(array.type().erasure())) {                    switch (primitives.getPrimitive(fun.symbol())) {                    case APPLY: return transformApply(tree);                    case UPDATE: return transformUpdate(tree);                    }                }            }	    Tree fun1 = transform(fun);            if (fun1.symbol() == definitions.NULL) return fun1.setType(owntype);	    if (global.debug) global.log("fn: " + fun1.symbol() + ":" + fun1.type);//debug	    switch (fun1.type) {	    case MethodType(Symbol[] params, Type restpe):		Tree[] args1 = args;		for (int i = 0; i < args.length; i++) {		    Tree arg = args[i];		    Type pt1 = params[i].type().erasure();		    Tree arg1 = cast(transform(arg, pt1), pt1);		    if (arg1 != arg && args1 == args) {			args1 = new Tree[args.length];			System.arraycopy(args, 0, args1, 0, i);		    }		    args1[i] = arg1;		}		return coerce(copy.Apply(tree, fun1, args1).setType(restpe), owntype);	    default:		global.debugPrinter.print(fun1);		throw Debug.abort("bad method type: " + Debug.show(fun1.type) + " " + Debug.show(fun1.symbol()));	    }	case Select(_, _):	case Ident(_):	    Tree tree1 = transformLhs(tree);	    //global.log("id: " + tree1+": "+tree1.type+" -> "+owntype);//DEBUG	    return (tree1.type instanceof Type.MethodType) ? tree1		: coerce(tree1, owntype);        case Empty:        case PackageDef(_,_):        case Template(_,_):        case Tuple(_): // !!! ?        case Super(_):        case This(_):        case Literal(_):        case TypeTerm():	    return super.transform(tree).setType(owntype);        case Bad():        case ModuleDef(_,_,_,_):        case PatDef(_,_,_):        case Import(_,_):        case CaseDef(_,_,_):        case LabelDef(_,_):        case Visitor(_):        case Function(_,_):        case SingletonType(_):        case SelectFromType(_,_):        case FunType(_,_):        case CompoundType(_,_):        case AppliedType(_, _):        case CovariantType(_):            throw Debug.abort("illegal case", tree);	default:            throw Debug.abort("unknown case", tree);	}    }