private JCExpression classOfType(Type type, DiagnosticPosition pos) {
        switch (type.tag) {
        case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
        case DOUBLE: case BOOLEAN: case VOID:
            // replace with <BoxedClass>.TYPE
            ClassSymbol c = types.boxedClass(type);
            Symbol typeSym =
                rs.access(
                    rs.findIdentInType(attrEnv, c.type, names.TYPE, VAR),
                    pos, c.type, names.TYPE, true);
            if (typeSym.kind == VAR)
                ((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
            return make.QualIdent(typeSym);
        case CLASS: case ARRAY:
            if (target.hasClassLiterals()) {
                VarSymbol sym = new VarSymbol(
                        STATIC | PUBLIC | FINAL, names._class,
                        syms.classType, type.tsym);
                return make_at(pos).Select(make.Type(type), sym);
            }
            // replace with <cache == null ? cache = class$(tsig) : cache>
            // where
            //  - <tsig>  is the type signature of T,
            //  - <cache> is the cache variable for tsig.
            String sig =
                writer.xClassName(type).toString().replace('/', '.');
            Symbol cs = cacheSym(pos, sig);
            return make_at(pos).Conditional(
                makeBinary(JCTree.EQ, make.Ident(cs), makeNull()),
                make.Assign(
                    make.Ident(cs),
                    make.App(
                        make.Ident(classDollarSym(pos)),
                        List.<JCExpression>of(make.Literal(CLASS, sig)
                                              .setType(syms.stringType))))
                .setType(types.erasure(syms.classType)),
                make.Ident(cs)).setType(types.erasure(syms.classType));
        default:
            throw new AssertionError();
        }
    }