return isSubType(tree, pt) ? tree : cast(tree, pt);
if (isSubType(tree.type(), pt)) { return tree; } else if (isUnboxed(tree.type) && !isUnboxed(pt)) { return coerce(box(tree), pt); } else if ((isUnboxedArray(tree.type) || (tree.type.symbol() == definitions.ANY_CLASS)) && isUnboxedArray(pt)) { return gen.mkAsInstanceOf(tree, pt); } else if (!isUnboxed(tree.type) && isUnboxed(pt)) { if (isBoxed(tree.type)) { return coerce(unbox(tree, pt), pt); } else { Type bt = boxedType(pt); while (isBoxed(bt.parents()[0])) { bt = bt.parents()[0]; } return coerce(coerce(tree, bt), pt); } } else if (isUnboxed(tree.type) && isUnboxed(pt)) { return gen.mkApply__(gen.Select(box(tree), unboxSym(pt))); } else if (!isUnboxed(tree.type) && !isUnboxed(pt) || isUnboxedArray(tree.type) && isUnboxedArray(pt)) { return gen.mkAsInstanceOf(tree, pt); } else { throw Debug.abort("cannot coerce " + tree.type + " to " + pt); }
    Tree coerce(Tree tree, Type pt) {	return isSubType(tree, pt) ? tree : cast(tree, pt);    }