Search in sources :

Example 16 with Type

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

the class Resolve method findInheritedMemberType.

/**
 * Find a member type inherited from a superclass or interface.
 *  @param env       The current environment.
 *  @param site      The original type from where the selection takes
 *                   place.
 *  @param name      The type's name.
 *  @param c         The class to search for the member type. This is
 *                   always a superclass or implemented interface of
 *                   site's class.
 */
Symbol findInheritedMemberType(Env<AttrContext> env, Type site, Name name, TypeSymbol c) {
    Symbol bestSoFar = typeNotFound;
    Symbol sym;
    Type st = types.supertype(c.type);
    if (st != null && st.hasTag(CLASS)) {
        sym = findMemberType(env, site, name, st.tsym);
        if (sym.kind < bestSoFar.kind)
            bestSoFar = sym;
    }
    for (List<Type> l = types.interfaces(c.type); bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); l = l.tail) {
        sym = findMemberType(env, site, name, l.head.tsym);
        if (bestSoFar.kind < AMBIGUOUS && sym.kind < AMBIGUOUS && sym.owner != bestSoFar.owner)
            bestSoFar = new AmbiguityError(bestSoFar, sym);
        else if (sym.kind < bestSoFar.kind)
            bestSoFar = sym;
    }
    return bestSoFar;
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type) DeferredType(org.eclipse.ceylon.langtools.tools.javac.comp.DeferredAttr.DeferredType) DiagnosticType(org.eclipse.ceylon.langtools.tools.javac.util.JCDiagnostic.DiagnosticType) Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol)

Example 17 with Type

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

the class Resolve method mostSpecific.

/* Return the most specific of the two methods for a call,
     *  given that both are accessible and applicable.
     *  @param m1               A new candidate for most specific.
     *  @param m2               The previous most specific candidate.
     *  @param env              The current environment.
     *  @param site             The original type from where the selection
     *                          takes place.
     *  @param allowBoxing Allow boxing conversions of arguments.
     *  @param useVarargs Box trailing arguments into an array for varargs.
     */
Symbol mostSpecific(List<Type> argtypes, Symbol m1, Symbol m2, Env<AttrContext> env, final Type site, boolean allowBoxing, boolean useVarargs) {
    switch(m2.kind) {
        case MTH:
            if (m1 == m2)
                return m1;
            boolean m1SignatureMoreSpecific = signatureMoreSpecific(argtypes, env, site, m1, m2, allowBoxing, useVarargs);
            boolean m2SignatureMoreSpecific = signatureMoreSpecific(argtypes, env, site, m2, m1, allowBoxing, useVarargs);
            if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
                Type mt1 = types.memberType(site, m1);
                Type mt2 = types.memberType(site, m2);
                if (!types.overrideEquivalent(mt1, mt2))
                    return ambiguityError(m1, m2);
                // one, or (d) merge both abstract signatures
                if ((m1.flags() & BRIDGE) != (m2.flags() & BRIDGE))
                    return ((m1.flags() & BRIDGE) != 0) ? m2 : m1;
                // if one overrides or hides the other, use it
                TypeSymbol m1Owner = (TypeSymbol) m1.owner;
                TypeSymbol m2Owner = (TypeSymbol) m2.owner;
                if (types.asSuper(m1Owner.type, m2Owner) != null && ((m1.owner.flags_field & INTERFACE) == 0 || (m2.owner.flags_field & INTERFACE) != 0) && m1.overrides(m2, m1Owner, types, false))
                    return m1;
                if (types.asSuper(m2Owner.type, m1Owner) != null && ((m2.owner.flags_field & INTERFACE) == 0 || (m1.owner.flags_field & INTERFACE) != 0) && m2.overrides(m1, m2Owner, types, false))
                    return m2;
                boolean m1Abstract = (m1.flags() & ABSTRACT) != 0;
                boolean m2Abstract = (m2.flags() & ABSTRACT) != 0;
                if (m1Abstract && !m2Abstract)
                    return m2;
                if (m2Abstract && !m1Abstract)
                    return m1;
                // both abstract or both concrete
                return ambiguityError(m1, m2);
            }
            if (m1SignatureMoreSpecific)
                return m1;
            if (m2SignatureMoreSpecific)
                return m2;
            return ambiguityError(m1, m2);
        case AMBIGUOUS:
            // compare m1 to ambiguous methods in m2
            AmbiguityError e = (AmbiguityError) m2.baseSymbol();
            boolean m1MoreSpecificThanAnyAmbiguous = true;
            boolean allAmbiguousMoreSpecificThanM1 = true;
            for (Symbol s : e.ambiguousSyms) {
                Symbol moreSpecific = mostSpecific(argtypes, m1, s, env, site, allowBoxing, useVarargs);
                m1MoreSpecificThanAnyAmbiguous &= moreSpecific == m1;
                allAmbiguousMoreSpecificThanM1 &= moreSpecific == s;
            }
            if (m1MoreSpecificThanAnyAmbiguous)
                return m1;
            // more specific than m1, add it as a new ambiguous method:
            if (!allAmbiguousMoreSpecificThanM1)
                e.addAmbiguousSymbol(m1);
            return e;
        default:
            throw new AssertionError();
    }
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type) DeferredType(org.eclipse.ceylon.langtools.tools.javac.comp.DeferredAttr.DeferredType) DiagnosticType(org.eclipse.ceylon.langtools.tools.javac.util.JCDiagnostic.DiagnosticType) Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol)

Example 18 with Type

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

the class Attr method visitConditional.

public void visitConditional(JCConditional tree) {
    Type condtype = attribExpr(tree.cond, env, syms.booleanType);
    tree.polyKind = (!allowPoly || pt().hasTag(NONE) && pt() != Type.recoveryType || isBooleanOrNumeric(env, tree)) ? PolyKind.STANDALONE : PolyKind.POLY;
    if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
        // cannot get here (i.e. it means we are returning from void method - which is already an error)
        resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void"));
        result = tree.type = types.createErrorType(resultInfo.pt);
        return;
    }
    ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ? unknownExprInfo : resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {

        // this will use enclosing check context to check compatibility of
        // subexpression against target type; if we are in a method check context,
        // depending on whether boxing is allowed, we could have incompatibilities
        @Override
        public void report(DiagnosticPosition pos, JCDiagnostic details) {
            enclosingContext.report(pos, diags.fragment("incompatible.type.in.conditional", details));
        }
    });
    Type truetype = attribTree(tree.truepart, env, condInfo);
    Type falsetype = attribTree(tree.falsepart, env, condInfo);
    Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, truetype, falsetype) : pt();
    if (condtype.constValue() != null && truetype.constValue() != null && falsetype.constValue() != null && !owntype.hasTag(NONE)) {
        // constant folding
        owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype);
    }
    result = check(tree, owntype, VAL, resultInfo);
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type) DiagnosticPosition(org.eclipse.ceylon.langtools.tools.javac.util.JCDiagnostic.DiagnosticPosition)

Example 19 with Type

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

the class Attr method visitReference.

@Override
public void visitReference(final JCMemberReference that) {
    if (pt().isErroneous() || (pt().hasTag(NONE) && pt() != Type.recoveryType)) {
        if (pt().hasTag(NONE)) {
            // method reference only allowed in assignment or method invocation/cast context
            log.error(that.pos(), "unexpected.mref");
        }
        result = that.type = types.createErrorType(pt());
        return;
    }
    final Env<AttrContext> localEnv = env.dup(that);
    try {
        // attribute member reference qualifier - if this is a constructor
        // reference, the expected kind must be a type
        Type exprType = attribTree(that.expr, env, memberReferenceQualifierResult(that));
        if (that.getMode() == JCMemberReference.ReferenceMode.NEW) {
            exprType = chk.checkConstructorRefType(that.expr, exprType);
            if (!exprType.isErroneous() && exprType.isRaw() && that.typeargs != null) {
                log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("mref.infer.and.explicit.params"));
                exprType = types.createErrorType(exprType);
            }
        }
        if (exprType.isErroneous()) {
            // if the qualifier expression contains problems,
            // give up attribution of method reference
            result = that.type = exprType;
            return;
        }
        if (TreeInfo.isStaticSelector(that.expr, names)) {
            // if the qualifier is a type, validate it; raw warning check is
            // omitted as we don't know at this stage as to whether this is a
            // raw selector (because of inference)
            chk.validate(that.expr, env, false);
        }
        // attrib type-arguments
        List<Type> typeargtypes = List.nil();
        if (that.typeargs != null) {
            typeargtypes = attribTypes(that.typeargs, localEnv);
        }
        Type desc;
        Type currentTarget = pt();
        boolean isTargetSerializable = resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && isSerializable(currentTarget);
        if (currentTarget != Type.recoveryType) {
            currentTarget = types.removeWildcards(targetChecker.visit(currentTarget, that));
            desc = types.findDescriptorType(currentTarget);
        } else {
            currentTarget = Type.recoveryType;
            desc = fallbackDescriptorType(that);
        }
        setFunctionalInfo(localEnv, that, pt(), desc, currentTarget, resultInfo.checkContext);
        List<Type> argtypes = desc.getParameterTypes();
        Resolve.MethodCheck referenceCheck = rs.resolveMethodCheck;
        if (resultInfo.checkContext.inferenceContext().free(argtypes)) {
            referenceCheck = rs.new MethodReferenceCheck(resultInfo.checkContext.inferenceContext());
        }
        Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = null;
        List<Type> saved_undet = resultInfo.checkContext.inferenceContext().save();
        try {
            refResult = rs.resolveMemberReference(localEnv, that, that.expr.type, that.name, argtypes, typeargtypes, referenceCheck, resultInfo.checkContext.inferenceContext(), resultInfo.checkContext.deferredAttrContext().mode);
        } finally {
            resultInfo.checkContext.inferenceContext().rollback(saved_undet);
        }
        Symbol refSym = refResult.fst;
        Resolve.ReferenceLookupHelper lookupHelper = refResult.snd;
        if (refSym.kind != MTH) {
            boolean targetError;
            switch(refSym.kind) {
                case ABSENT_MTH:
                    targetError = false;
                    break;
                case WRONG_MTH:
                case WRONG_MTHS:
                case AMBIGUOUS:
                case HIDDEN:
                case STATICERR:
                case MISSING_ENCL:
                case WRONG_STATICNESS:
                    targetError = true;
                    break;
                default:
                    Assert.error("unexpected result kind " + refSym.kind);
                    targetError = false;
            }
            JCDiagnostic detailsDiag = ((Resolve.ResolveError) refSym.baseSymbol()).getDiagnostic(JCDiagnostic.DiagnosticType.FRAGMENT, that, exprType.tsym, exprType, that.name, argtypes, typeargtypes);
            JCDiagnostic.DiagnosticType diagKind = targetError ? JCDiagnostic.DiagnosticType.FRAGMENT : JCDiagnostic.DiagnosticType.ERROR;
            JCDiagnostic diag = diags.create(diagKind, log.currentSource(), that, "invalid.mref", Kinds.kindName(that.getMode()), detailsDiag);
            if (targetError && currentTarget == Type.recoveryType) {
                // a target error doesn't make sense during recovery stage
                // as we don't know what actual parameter types are
                result = that.type = currentTarget;
                return;
            } else {
                if (targetError) {
                    resultInfo.checkContext.report(that, diag);
                } else {
                    log.report(diag);
                }
                result = that.type = types.createErrorType(currentTarget);
                return;
            }
        }
        that.sym = refSym.baseSymbol();
        that.kind = lookupHelper.referenceKind(that.sym);
        that.ownerAccessible = rs.isAccessible(localEnv, that.sym.enclClass());
        if (desc.getReturnType() == Type.recoveryType) {
            // stop here
            result = that.type = currentTarget;
            return;
        }
        if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
            if (that.getMode() == ReferenceMode.INVOKE && TreeInfo.isStaticSelector(that.expr, names) && that.kind.isUnbound() && !desc.getParameterTypes().head.isParameterized()) {
                chk.checkRaw(that.expr, localEnv);
            }
            if (that.sym.isStatic() && TreeInfo.isStaticSelector(that.expr, names) && exprType.getTypeArguments().nonEmpty()) {
                // static ref with class type-args
                log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("static.mref.with.targs"));
                result = that.type = types.createErrorType(currentTarget);
                return;
            }
            if (that.sym.isStatic() && !TreeInfo.isStaticSelector(that.expr, names) && !that.kind.isUnbound()) {
                // no static bound mrefs
                log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), diags.fragment("static.bound.mref"));
                result = that.type = types.createErrorType(currentTarget);
                return;
            }
            if (!refSym.isStatic() && that.kind == JCMemberReference.ReferenceKind.SUPER) {
                // Check that super-qualified symbols are not abstract (JLS)
                rs.checkNonAbstract(that.pos(), that.sym);
            }
            if (isTargetSerializable) {
                chk.checkElemAccessFromSerializableLambda(that);
            }
        }
        ResultInfo checkInfo = resultInfo.dup(newMethodTemplate(desc.getReturnType().hasTag(VOID) ? Type.noType : desc.getReturnType(), that.kind.isUnbound() ? argtypes.tail : argtypes, typeargtypes), new FunctionalReturnContext(resultInfo.checkContext));
        Type refType = checkId(noCheckTree, lookupHelper.site, refSym, localEnv, checkInfo);
        if (that.kind.isUnbound() && resultInfo.checkContext.inferenceContext().free(argtypes.head)) {
            // re-generate inference constraints for unbound receiver
            if (!types.isSubtype(resultInfo.checkContext.inferenceContext().asUndetVar(argtypes.head), exprType)) {
                // cannot happen as this has already been checked - we just need
                // to regenerate the inference constraints, as that has been lost
                // as a result of the call to inferenceContext.save()
                Assert.error("Can't get here");
            }
        }
        if (!refType.isErroneous()) {
            refType = types.createMethodTypeWithReturn(refType, adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
        }
        // go ahead with standard method reference compatibility check - note that param check
        // is a no-op (as this has been taken care during method applicability)
        boolean isSpeculativeRound = resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
        // avoids recovery at this stage
        that.type = currentTarget;
        checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound);
        if (!isSpeculativeRound) {
            checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, currentTarget);
        }
        result = check(that, currentTarget, VAL, resultInfo);
    } catch (Types.FunctionDescriptorLookupError ex) {
        JCDiagnostic cause = ex.getDiagnostic();
        resultInfo.checkContext.report(that, cause);
        result = that.type = types.createErrorType(pt());
        return;
    }
}
Also used : Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol) Type(org.eclipse.ceylon.langtools.tools.javac.code.Type)

Example 20 with Type

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

the class Attr method checkReferenceCompatible.

@SuppressWarnings("fallthrough")
void checkReferenceCompatible(JCMemberReference tree, Type descriptor, Type refType, CheckContext checkContext, boolean speculativeAttr) {
    Type returnType = checkContext.inferenceContext().asUndetVar(descriptor.getReturnType());
    Type resType;
    switch(tree.getMode()) {
        case NEW:
            if (!tree.expr.type.isRaw()) {
                resType = tree.expr.type;
                break;
            }
        default:
            resType = refType.getReturnType();
    }
    Type incompatibleReturnType = resType;
    if (returnType.hasTag(VOID)) {
        incompatibleReturnType = null;
    }
    if (!returnType.hasTag(VOID) && !resType.hasTag(VOID)) {
        if (resType.isErroneous() || new FunctionalReturnContext(checkContext).compatible(resType, returnType, types.noWarnings)) {
            incompatibleReturnType = null;
        }
    }
    if (incompatibleReturnType != null) {
        checkContext.report(tree, diags.fragment("incompatible.ret.type.in.mref", diags.fragment("inconvertible.types", resType, descriptor.getReturnType())));
    }
    if (!speculativeAttr) {
        List<Type> thrownTypes = checkContext.inferenceContext().asUndetVars(descriptor.getThrownTypes());
        if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) {
            log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes());
        }
    }
}
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