Search in sources :

Example 56 with Type

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

the class Infer method instantiateMethod.

// <editor-fold defaultstate="collapsed" desc="Inference routines">
/**
 * Main inference entry point - instantiate a generic method type
 * using given argument types and (possibly) an expected target-type.
 */
Type instantiateMethod(Env<AttrContext> env, List<Type> tvars, MethodType mt, Attr.ResultInfo resultInfo, MethodSymbol msym, List<Type> argtypes, boolean allowBoxing, boolean useVarargs, Resolve.MethodResolutionContext resolveContext, Warner warn) throws InferenceException {
    // -System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
    // B0
    final InferenceContext inferenceContext = new InferenceContext(tvars);
    inferenceException.clear();
    try {
        DeferredAttr.DeferredAttrContext deferredAttrContext = resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
        // B2
        resolveContext.methodCheck.argumentsAcceptable(// B2
        env, // B2
        deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
        if (allowGraphInference && resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
            // inject return constraints earlier
            // propagation
            checkWithinBounds(inferenceContext, warn);
            Type newRestype = generateReturnConstraints(// B3
            env.tree, // B3
            resultInfo, mt, inferenceContext);
            mt = (MethodType) types.createMethodTypeWithReturn(mt, newRestype);
            // propagate outwards if needed
            if (resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
                // propagate inference context outwards and exit
                inferenceContext.dupTo(resultInfo.checkContext.inferenceContext());
                deferredAttrContext.complete();
                return mt;
            }
        }
        deferredAttrContext.complete();
        // minimize as yet undetermined type variables
        if (allowGraphInference) {
            inferenceContext.solve(warn);
        } else {
            // minimizeInst
            inferenceContext.solveLegacy(true, warn, LegacyInferenceSteps.EQ_LOWER.steps);
        }
        mt = (MethodType) inferenceContext.asInstType(mt);
        if (!allowGraphInference && inferenceContext.restvars().nonEmpty() && resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
            generateReturnConstraints(env.tree, resultInfo, mt, inferenceContext);
            // maximizeInst
            inferenceContext.solveLegacy(false, warn, LegacyInferenceSteps.EQ_UPPER.steps);
            mt = (MethodType) inferenceContext.asInstType(mt);
        }
        if (resultInfo != null && rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
            log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
        }
        // return instantiated version of method type
        return mt;
    } finally {
        if (resultInfo != null || !allowGraphInference) {
            inferenceContext.notifyChange();
        } else {
            inferenceContext.notifyChange(inferenceContext.boundedVars());
        }
        if (resultInfo == null) {
            /* if the is no result info then we can clear the capture types
                 * cache without affecting any result info check
                 */
            inferenceContext.captureTypeCache.clear();
        }
    }
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type)

Example 57 with Type

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

the class Infer method generateReturnConstraints.

/**
 * Generate constraints from the generic method's return type. If the method
 * call occurs in a context where a type T is expected, use the expected
 * type to derive more constraints on the generic method inference variables.
 */
Type generateReturnConstraints(JCTree tree, Attr.ResultInfo resultInfo, MethodType mt, InferenceContext inferenceContext) {
    InferenceContext rsInfoInfContext = resultInfo.checkContext.inferenceContext();
    Type from = mt.getReturnType();
    if (mt.getReturnType().containsAny(inferenceContext.inferencevars) && rsInfoInfContext != emptyContext) {
        from = types.capture(from);
        // add synthetic captured ivars
        for (Type t : from.getTypeArguments()) {
            if (t.hasTag(TYPEVAR) && ((TypeVar) t).isCaptured()) {
                inferenceContext.addVar((TypeVar) t);
            }
        }
    }
    Type qtype = inferenceContext.asUndetVar(from);
    Type to = resultInfo.pt;
    if (qtype.hasTag(VOID)) {
        to = syms.voidType;
    } else if (to.hasTag(NONE)) {
        to = from.isPrimitive() ? from : syms.objectType;
    } else if (qtype.hasTag(UNDETVAR)) {
        if (resultInfo.pt.isReference()) {
            to = generateReturnConstraintsUndetVarToReference(tree, (UndetVar) qtype, to, resultInfo, inferenceContext);
        } else {
            if (to.isPrimitive()) {
                to = generateReturnConstraintsPrimitive(tree, (UndetVar) qtype, to, resultInfo, inferenceContext);
            }
        }
    }
    Assert.check(allowGraphInference || !rsInfoInfContext.free(to), "legacy inference engine cannot handle constraints on both sides of a subtyping assertion");
    // we need to skip capture?
    Warner retWarn = new Warner();
    if (!resultInfo.checkContext.compatible(qtype, rsInfoInfContext.asUndetVar(to), retWarn) || // unchecked conversion is not allowed in source 7 mode
    (!allowGraphInference && retWarn.hasLint(Lint.LintCategory.UNCHECKED))) {
        throw inferenceException.setMessage("infer.no.conforming.instance.exists", inferenceContext.restvars(), mt.getReturnType(), to);
    }
    return from;
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type)

Example 58 with Type

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

the class LambdaToMethod method makeLambdaExpressionBody.

private JCBlock makeLambdaExpressionBody(JCExpression expr, JCMethodDecl lambdaMethodDecl) {
    Type restype = lambdaMethodDecl.type.getReturnType();
    boolean isLambda_void = expr.type.hasTag(VOID);
    boolean isTarget_void = restype.hasTag(VOID);
    boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type);
    int prevPos = make.pos;
    try {
        if (isTarget_void) {
            // target is void:
            // BODY;
            JCStatement stat = make.at(expr).Exec(expr);
            return make.Block(0, List.<JCStatement>of(stat));
        } else if (isLambda_void && isTarget_Void) {
            // void to Void conversion:
            // BODY; return null;
            ListBuffer<JCStatement> stats = new ListBuffer<>();
            stats.append(make.at(expr).Exec(expr));
            stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType)));
            return make.Block(0, stats.toList());
        } else {
            // non-void to non-void conversion:
            // return (TYPE)BODY;
            JCExpression retExpr = transTypes.coerce(attrEnv, expr, restype);
            return make.at(retExpr).Block(0, List.<JCStatement>of(make.Return(retExpr)));
        }
    } finally {
        make.at(prevPos);
    }
}
Also used : MethodType(org.eclipse.ceylon.langtools.tools.javac.code.Type.MethodType) Type(org.eclipse.ceylon.langtools.tools.javac.code.Type)

Example 59 with Type

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

the class LambdaToMethod method makeMetafactoryIndyCall.

/**
 * Generate an indy method call to the meta factory
 */
private JCExpression makeMetafactoryIndyCall(LambdaAnalyzerPreprocessor.TranslationContext<?> context, int refKind, Symbol refSym, List<JCExpression> indy_args) {
    JCFunctionalExpression tree = context.tree;
    // determine the static bsm args
    MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
    List<Object> staticArgs = List.<Object>of(typeToMethodType(samSym.type), new Pool.MethodHandle(refKind, refSym, types), typeToMethodType(tree.getDescriptorType(types)));
    // computed indy arg types
    ListBuffer<Type> indy_args_types = new ListBuffer<>();
    for (JCExpression arg : indy_args) {
        indy_args_types.append(arg.type);
    }
    // finally, compute the type of the indy call
    MethodType indyType = new MethodType(indy_args_types.toList(), tree.type, List.<Type>nil(), syms.methodClass);
    Name metafactoryName = context.needsAltMetafactory() ? names.altMetafactory : names.metafactory;
    if (context.needsAltMetafactory()) {
        ListBuffer<Object> markers = new ListBuffer<>();
        for (Type t : tree.targets.tail) {
            if (t.tsym != syms.serializableType.tsym) {
                markers.append(t.tsym);
            }
        }
        int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;
        boolean hasMarkers = markers.nonEmpty();
        boolean hasBridges = context.bridges.nonEmpty();
        if (hasMarkers) {
            flags |= FLAG_MARKERS;
        }
        if (hasBridges) {
            flags |= FLAG_BRIDGES;
        }
        staticArgs = staticArgs.append(flags);
        if (hasMarkers) {
            staticArgs = staticArgs.append(markers.length());
            staticArgs = staticArgs.appendList(markers.toList());
        }
        if (hasBridges) {
            staticArgs = staticArgs.append(context.bridges.length() - 1);
            for (Symbol s : context.bridges) {
                Type s_erasure = s.erasure(types);
                if (!types.isSameType(s_erasure, samSym.erasure(types))) {
                    staticArgs = staticArgs.append(s.erasure(types));
                }
            }
        }
        if (context.isSerializable()) {
            int prevPos = make.pos;
            try {
                make.at(kInfo.clazz);
                addDeserializationCase(refKind, refSym, tree.type, samSym, tree, staticArgs, indyType);
            } finally {
                make.at(prevPos);
            }
        }
    }
    return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name);
}
Also used : MethodType(org.eclipse.ceylon.langtools.tools.javac.code.Type.MethodType) VarSymbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol.VarSymbol) MethodSymbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol.MethodSymbol) Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol) TypeSymbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol.TypeSymbol) DynamicMethodSymbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol.DynamicMethodSymbol) ClassSymbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol.ClassSymbol) MethodType(org.eclipse.ceylon.langtools.tools.javac.code.Type.MethodType) Type(org.eclipse.ceylon.langtools.tools.javac.code.Type) MethodSymbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol.MethodSymbol) DynamicMethodSymbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol.DynamicMethodSymbol)

Example 60 with Type

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

the class LambdaToMethod method makeLambdaStatementBody.

private JCBlock makeLambdaStatementBody(JCBlock block, final JCMethodDecl lambdaMethodDecl, boolean completeNormally) {
    final Type restype = lambdaMethodDecl.type.getReturnType();
    final boolean isTarget_void = restype.hasTag(VOID);
    boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type);
    class LambdaBodyTranslator extends TreeTranslator {

        @Override
        public void visitClassDef(JCClassDecl tree) {
            // do NOT recurse on any inner classes
            result = tree;
        }

        @Override
        public void visitLambda(JCLambda tree) {
            // do NOT recurse on any nested lambdas
            result = tree;
        }

        @Override
        public void visitReturn(JCReturn tree) {
            boolean isLambda_void = tree.expr == null;
            if (isTarget_void && !isLambda_void) {
                // Void to void conversion:
                // { TYPE $loc = RET-EXPR; return; }
                VarSymbol loc = makeSyntheticVar(0, names.fromString("$loc"), tree.expr.type, lambdaMethodDecl.sym);
                JCVariableDecl varDef = make.VarDef(loc, tree.expr);
                result = make.Block(0, List.<JCStatement>of(varDef, make.Return(null)));
            } else if (!isTarget_void || !isLambda_void) {
                // non-void to non-void conversion:
                // return (TYPE)RET-EXPR;
                tree.expr = transTypes.coerce(attrEnv, tree.expr, restype);
                result = tree;
            } else {
                result = tree;
            }
        }
    }
    JCBlock trans_block = new LambdaBodyTranslator().translate(block);
    if (completeNormally && isTarget_Void) {
        // there's no return statement and the lambda (possibly inferred)
        // return type is java.lang.Void; emit a synthetic return statement
        trans_block.stats = trans_block.stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType)));
    }
    return trans_block;
}
Also used : MethodType(org.eclipse.ceylon.langtools.tools.javac.code.Type.MethodType) Type(org.eclipse.ceylon.langtools.tools.javac.code.Type) TreeTranslator(org.eclipse.ceylon.langtools.tools.javac.tree.TreeTranslator) VarSymbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol.VarSymbol)

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