Search in sources :

Example 26 with Type

use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.

the class Attr method visitTypeApply.

/**
 * Visitor method for parameterized types.
 *  Bound checking is left until later, since types are attributed
 *  before supertype structure is completely known
 */
public void visitTypeApply(JCTypeApply tree) {
    Type owntype = types.createErrorType(tree.type);
    // Attribute functor part of application and make sure it's a class.
    Type clazztype = chk.checkClassType(tree.clazz.pos(), attribType(tree.clazz, env));
    // Attribute type parameters
    List<Type> actuals = attribTypes(tree.arguments, env);
    if (clazztype.hasTag(CLASS)) {
        List<Type> formals = clazztype.tsym.type.getTypeArguments();
        if (// diamond
        actuals.isEmpty())
            actuals = formals;
        if (actuals.length() == formals.length()) {
            List<Type> a = actuals;
            List<Type> f = formals;
            while (a.nonEmpty()) {
                a.head = a.head.withTypeVar(f.head);
                a = a.tail;
                f = f.tail;
            }
            // Compute the proper generic outer
            Type clazzOuter = clazztype.getEnclosingType();
            if (clazzOuter.hasTag(CLASS)) {
                Type site;
                JCExpression clazz = TreeInfo.typeIn(tree.clazz);
                if (clazz.hasTag(IDENT)) {
                    site = env.enclClass.sym.type;
                } else if (clazz.hasTag(SELECT)) {
                    site = ((JCFieldAccess) clazz).selected.type;
                } else
                    throw new AssertionError("" + tree);
                if (clazzOuter.hasTag(CLASS) && site != clazzOuter) {
                    if (site.hasTag(CLASS))
                        site = types.asOuterSuper(site, clazzOuter.tsym);
                    if (site == null)
                        site = types.erasure(clazzOuter);
                    clazzOuter = site;
                }
            }
            owntype = new ClassType(clazzOuter, actuals, clazztype.tsym);
        } else {
            if (formals.length() != 0) {
                log.error(tree.pos(), "wrong.number.type.args", Integer.toString(formals.length()));
            } else {
                log.error(tree.pos(), "type.doesnt.take.params", clazztype.tsym);
            }
            owntype = types.createErrorType(tree.type);
        }
    }
    result = check(tree, owntype, TYP, resultInfo);
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type)

Example 27 with Type

use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.

the class Attr method visitApply.

/**
 * Visitor method for method invocations.
 *  NOTE: The method part of an application will have in its type field
 *        the return type of the method, not the method's type itself!
 */
public void visitApply(JCMethodInvocation tree) {
    // The local environment of a method application is
    // a new environment nested in the current one.
    Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
    // The types of the actual method arguments.
    List<Type> argtypes;
    // The types of the actual method type arguments.
    List<Type> typeargtypes = null;
    Name methName = TreeInfo.name(tree.meth);
    boolean isConstructorCall = methName == names._this || methName == names._super;
    ListBuffer<Type> argtypesBuf = new ListBuffer<>();
    if (isConstructorCall) {
        // Check that this is the first statement in a constructor.
        if (checkFirstConstructorStat(tree, env)) {
            // Record the fact
            // that this is a constructor call (using isSelfCall).
            localEnv.info.isSelfCall = true;
            // Attribute arguments, yielding list of argument types.
            int kind = attribArgs(MTH, tree.args, localEnv, argtypesBuf);
            argtypes = argtypesBuf.toList();
            typeargtypes = attribTypes(tree.typeargs, localEnv);
            // Variable `site' points to the class in which the called
            // constructor is defined.
            Type site = env.enclClass.sym.type;
            if (methName == names._super) {
                if (site == syms.objectType) {
                    log.error(tree.meth.pos(), "no.superclass", site);
                    site = types.createErrorType(syms.objectType);
                } else {
                    site = types.supertype(site);
                }
            }
            if (site.hasTag(CLASS)) {
                Type encl = site.getEnclosingType();
                while (encl != null && encl.hasTag(TYPEVAR)) encl = encl.getUpperBound();
                if (encl.hasTag(CLASS)) {
                    if (tree.meth.hasTag(SELECT)) {
                        JCTree qualifier = ((JCFieldAccess) tree.meth).selected;
                        // We are seeing a prefixed call, of the form
                        // <expr>.super(...).
                        // Check that the prefix expression conforms
                        // to the outer instance type of the class.
                        chk.checkRefType(qualifier.pos(), attribExpr(qualifier, localEnv, encl));
                    } else if (methName == names._super) {
                        // qualifier omitted; check for existence
                        // of an appropriate implicit qualifier.
                        rs.resolveImplicitThis(tree.meth.pos(), localEnv, site, true);
                    }
                } else if (tree.meth.hasTag(SELECT)) {
                    log.error(tree.meth.pos(), "illegal.qual.not.icls", site.tsym);
                }
                // prefix the implicit String and int parameters
                if (site.tsym == syms.enumSym && allowEnums)
                    argtypes = argtypes.prepend(syms.intType).prepend(syms.stringType);
                // Resolve the called constructor under the assumption
                // that we are referring to a superclass instance of the
                // current instance (JLS ???).
                boolean selectSuperPrev = localEnv.info.selectSuper;
                localEnv.info.selectSuper = true;
                localEnv.info.pendingResolutionPhase = null;
                Symbol sym = rs.resolveConstructor(tree.meth.pos(), localEnv, site, argtypes, typeargtypes);
                localEnv.info.selectSuper = selectSuperPrev;
                // Set method symbol to resolved constructor...
                TreeInfo.setSymbol(tree.meth, sym);
                // ...and check that it is legal in the current context.
                // (this will also set the tree's type)
                Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes);
                checkId(tree.meth, site, sym, localEnv, new ResultInfo(kind, mpt));
            }
        // Otherwise, `site' is an error type and we do nothing
        }
        result = tree.type = syms.voidType;
    } else {
        // Otherwise, we are seeing a regular method call.
        // Attribute the arguments, yielding list of argument types, ...
        int kind = attribArgs(VAL, tree.args, localEnv, argtypesBuf);
        argtypes = argtypesBuf.toList();
        typeargtypes = attribAnyTypes(tree.typeargs, localEnv);
        // ... and attribute the method using as a prototype a methodtype
        // whose formal argument types is exactly the list of actual
        // arguments (this will also set the method symbol).
        Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes);
        localEnv.info.pendingResolutionPhase = null;
        Type mtype = attribTree(tree.meth, localEnv, new ResultInfo(kind, mpt, resultInfo.checkContext));
        // Compute the result type.
        Type restype = mtype.getReturnType();
        if (restype.hasTag(TypeTag.WILDCARD))
            throw new AssertionError(mtype);
        Type qualifier = (tree.meth.hasTag(SELECT)) ? ((JCFieldAccess) tree.meth).selected.type : env.enclClass.sym.type;
        restype = adjustMethodReturnType(qualifier, methName, argtypes, restype);
        chk.checkRefTypes(tree.typeargs, typeargtypes);
        // Check that value of resulting type is admissible in the
        // current context.  Also, capture the return type
        result = check(tree, capture(restype), VAL, resultInfo);
    }
    chk.validate(tree.typeargs, localEnv);
}
Also used : Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Type(org.eclipse.ceylon.langtools.tools.javac.code.Type)

Example 28 with Type

use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.

the class Attr method lambdaEnv.

/* This method returns an environment to be used to attribute a lambda
         * expression.
         *
         * The owner of this environment is a method symbol. If the current owner
         * is not a method, for example if the lambda is used to initialize
         * a field, then if the field is:
         *
         * - an instance field, we use the first constructor.
         * - a static field, we create a fake clinit method.
         */
public Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) {
    Env<AttrContext> lambdaEnv;
    Symbol owner = env.info.scope.owner;
    if (owner.kind == VAR && owner.owner.kind == TYP) {
        // field initializer
        lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared()));
        ClassSymbol enclClass = owner.enclClass();
        /* if the field isn't static, then we can get the first constructor
                 * and use it as the owner of the environment. This is what
                 * LTM code is doing to look for type annotations so we are fine.
                 */
        if ((owner.flags() & STATIC) == 0) {
            for (Symbol s : enclClass.members_field.getElementsByName(names.init)) {
                lambdaEnv.info.scope.owner = s;
                break;
            }
        } else {
            /* if the field is static then we need to create a fake clinit
                     * method, this method can later be reused by LTM.
                     */
            MethodSymbol clinit = clinits.get(enclClass);
            if (clinit == null) {
                Type clinitType = new MethodType(List.<Type>nil(), syms.voidType, List.<Type>nil(), syms.methodClass);
                clinit = new MethodSymbol(STATIC | SYNTHETIC | PRIVATE, names.clinit, clinitType, enclClass);
                clinit.params = List.<VarSymbol>nil();
                clinits.put(enclClass, clinit);
            }
            lambdaEnv.info.scope.owner = clinit;
        }
    } else {
        lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
    }
    return lambdaEnv;
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type) Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol)

Example 29 with Type

use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.

the class Attr method visitSwitch.

public void visitSwitch(JCSwitch tree) {
    Type seltype = attribExpr(tree.selector, env);
    Env<AttrContext> switchEnv = env.dup(tree, env.info.dup(env.info.scope.dup()));
    try {
        boolean enumSwitch = allowEnums && (seltype.tsym.flags() & Flags.ENUM) != 0;
        boolean stringSwitch = false;
        if (types.isSameType(seltype, syms.stringType)) {
            if (allowStringsInSwitch) {
                stringSwitch = true;
            } else {
                log.error(tree.selector.pos(), "string.switch.not.supported.in.source", sourceName);
            }
        }
        if (!enumSwitch && !stringSwitch)
            seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType);
        // Attribute all cases and
        // check that there are no duplicate case labels or default clauses.
        // The set of case labels.
        Set<Object> labels = new HashSet<Object>();
        // Is there a default label?
        boolean hasDefault = false;
        for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
            JCCase c = l.head;
            Env<AttrContext> caseEnv = switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
            try {
                if (c.pat != null) {
                    if (enumSwitch) {
                        Symbol sym = enumConstant(c.pat, seltype);
                        if (sym == null) {
                            log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum");
                        } else if (!labels.add(sym)) {
                            log.error(c.pos(), "duplicate.case.label");
                        }
                    } else {
                        Type pattype = attribExpr(c.pat, switchEnv, seltype);
                        if (!pattype.hasTag(ERROR)) {
                            if (pattype.constValue() == null) {
                                log.error(c.pat.pos(), (stringSwitch ? "string.const.req" : "const.expr.req"));
                            } else if (labels.contains(pattype.constValue())) {
                                log.error(c.pos(), "duplicate.case.label");
                            } else {
                                labels.add(pattype.constValue());
                            }
                        }
                    }
                } else if (hasDefault) {
                    log.error(c.pos(), "duplicate.default.label");
                } else {
                    hasDefault = true;
                }
                attribStats(c.stats, caseEnv);
            } finally {
                caseEnv.info.scope.leave();
                addVars(c.stats, switchEnv.info.scope);
            }
        }
        result = null;
    } finally {
        switchEnv.info.scope.leave();
    }
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type) Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol) JavaFileObject(org.eclipse.ceylon.javax.tools.JavaFileObject)

Example 30 with Type

use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.

the class Attr method visitTypeCast.

public void visitTypeCast(final JCTypeCast tree) {
    Type clazztype = attribType(tree.clazz, env);
    chk.validate(tree.clazz, env, false);
    // a fresh environment is required for 292 inference to work properly ---
    // see Infer.instantiatePolymorphicSignatureInstance()
    Env<AttrContext> localEnv = env.dup(tree);
    // should we propagate the target type?
    final ResultInfo castInfo;
    JCExpression expr = TreeInfo.skipParens(tree.expr);
    boolean isPoly = allowPoly && (expr.hasTag(LAMBDA) || expr.hasTag(REFERENCE));
    if (isPoly) {
        // expression is a poly - we need to propagate target type info
        castInfo = new ResultInfo(VAL, clazztype, new Check.NestedCheckContext(resultInfo.checkContext) {

            @Override
            public boolean compatible(Type found, Type req, Warner warn) {
                return types.isCastable(found, req, warn);
            }
        });
    } else {
        // standalone cast - target-type info is not propagated
        castInfo = unknownExprInfo;
    }
    Type exprtype = attribTree(tree.expr, localEnv, castInfo);
    Type owntype = isPoly ? clazztype : chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
    if (exprtype.constValue() != null)
        owntype = cfolder.coerce(exprtype, owntype);
    result = check(tree, capture(owntype), VAL, resultInfo);
    if (!isPoly)
        chk.checkRedundantCast(localEnv, tree);
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type)

Aggregations

Type (org.eclipse.ceylon.langtools.tools.javac.code.Type)164 Symbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol)46 DeferredType (org.eclipse.ceylon.langtools.tools.javac.comp.DeferredAttr.DeferredType)13 DiagnosticType (org.eclipse.ceylon.langtools.tools.javac.util.JCDiagnostic.DiagnosticType)13 ArrayType (org.eclipse.ceylon.langtools.tools.javac.code.Type.ArrayType)10 MethodType (org.eclipse.ceylon.langtools.tools.javac.code.Type.MethodType)10 ClassSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.ClassSymbol)9 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)9 MethodSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.MethodSymbol)8 JavaFileObject (org.eclipse.ceylon.javax.tools.JavaFileObject)7 TypeSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.TypeSymbol)7 DiagnosticPosition (org.eclipse.ceylon.langtools.tools.javac.util.JCDiagnostic.DiagnosticPosition)7 JavacType (org.eclipse.ceylon.compiler.java.loader.mirror.JavacType)5 PackageSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.PackageSymbol)5 FunctionalInterfaceType (org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType)5 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)5 HashSet (java.util.HashSet)4 CompletionFailure (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.CompletionFailure)4 VarSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.VarSymbol)4 FreeTypeListener (org.eclipse.ceylon.langtools.tools.javac.comp.Infer.FreeTypeListener)4