Search in sources :

Example 71 with TypeParameter

use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.

the class RefinementVisitor method visit.

@Override
public void visit(Tree.Declaration that) {
    super.visit(that);
    Declaration dec = that.getDeclarationModel();
    if (dec != null) {
        boolean mayBeShared = dec.isToplevel() || dec.isClassOrInterfaceMember();
        if (dec.isShared() && !mayBeShared) {
            that.addError("shared declaration is not a member of a class, interface, or package: " + message(dec) + " may not be annotated 'shared'", 1200);
        }
        boolean mayBeRefined = dec instanceof Value || dec instanceof Function || dec instanceof Class;
        if (!mayBeRefined) {
            checkNonrefinableDeclaration(that, dec);
        }
        boolean member = dec.isClassOrInterfaceMember() && dec.isShared() && !isConstructor(dec) && // TODO: what about nested interfaces and abstract classes?!
        !(dec instanceof TypeParameter);
        if (member) {
            checkMember(that, dec);
        } else {
            checkNonMember(that, dec);
        }
        if (dec.isNativeImplementation() || isNativeMember(dec)) {
            checkNative(that, dec);
        }
    }
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Example 72 with TypeParameter

use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.

the class RefinementVisitor method checkRefiningMemberUpperBounds.

private List<Type> checkRefiningMemberUpperBounds(Tree.Declaration that, ClassOrInterface ci, Declaration refined, List<TypeParameter> refinedTypeParams, List<TypeParameter> refiningTypeParams) {
    int refiningSize = refiningTypeParams.size();
    int refinedSize = refinedTypeParams.size();
    int max = refiningSize <= refinedSize ? refiningSize : refinedSize;
    if (max == 0) {
        return NO_TYPE_ARGS;
    }
    // we substitute the type parameters of the refined
    // declaration into the bounds of the refining
    // declaration
    Map<TypeParameter, Type> substitution = new HashMap<TypeParameter, Type>();
    for (int i = 0; i < max; i++) {
        TypeParameter refinedTypeParam = refinedTypeParams.get(i);
        TypeParameter refiningTypeParam = refiningTypeParams.get(i);
        substitution.put(refiningTypeParam, refinedTypeParam.getType());
    }
    Map<TypeParameter, SiteVariance> noVariances = emptyMap();
    TypeDeclaration rc = (TypeDeclaration) refined.getContainer();
    // we substitute the type arguments of the subtype's
    // instantiation of the supertype into the bounds of
    // the refined declaration
    Type supertype = ci.getType().getSupertype(rc);
    Map<TypeParameter, Type> args = supertype.getTypeArguments();
    Map<TypeParameter, SiteVariance> variances = supertype.getVarianceOverrides();
    List<Type> typeArgs = new ArrayList<Type>(max);
    for (int i = 0; i < max; i++) {
        TypeParameter refinedTypeParam = refinedTypeParams.get(i);
        TypeParameter refiningTypeParam = refiningTypeParams.get(i);
        refiningTypeParam.setReified(refinedTypeParam.isReified());
        Type refinedProducedType = refinedTypeParam.getType();
        List<Type> refinedBounds = refinedTypeParam.getSatisfiedTypes();
        List<Type> refiningBounds = refiningTypeParam.getSatisfiedTypes();
        Unit unit = that.getUnit();
        for (Type bound : refiningBounds) {
            Type refiningBound = bound.substitute(substitution, noVariances);
            // for every type constraint of the refining member, there must
            // be at least one type constraint of the refined member which
            // is assignable to it, guaranteeing that the intersection of
            // the refined member bounds is assignable to the intersection
            // of the refining member bounds
            // TODO: would it be better to just form the intersections and
            // test assignability directly (the error messages might
            // not be as helpful, but it might be less restrictive)
            boolean ok = false;
            for (Type refinedBound : refinedBounds) {
                refinedBound = refinedBound.substitute(args, variances);
                if (refinedBound.isSubtypeOf(refiningBound)) {
                    ok = true;
                }
            }
            if (!ok) {
                that.addError("refining member type parameter '" + refiningTypeParam.getName() + "' has upper bound which refined member type parameter '" + refinedTypeParam.getName() + "' of " + message(refined) + " does not satisfy: '" + bound.asString(unit) + "' ('" + refiningTypeParam.getName() + "' should be upper bounded by '" + intersectionOfSupertypes(refinedTypeParam).substitute(args, variances).asString(unit) + "')");
            }
        }
        for (Type bound : refinedBounds) {
            Type refinedBound = bound.substitute(args, variances);
            boolean ok = false;
            for (Type refiningBound : refiningBounds) {
                refiningBound = refiningBound.substitute(substitution, noVariances);
                if (refinedBound.isSubtypeOf(refiningBound)) {
                    ok = true;
                }
            }
            if (!ok) {
                that.addUnsupportedError("refined member type parameter '" + refinedTypeParam.getName() + "' of " + message(refined) + " has upper bound which refining member type parameter '" + refiningTypeParam.getName() + "' does not satisfy: '" + bound.asString(unit) + "' ('" + refiningTypeParam.getName() + "' should be upper bounded by '" + intersectionOfSupertypes(refinedTypeParam).substitute(args, variances).asString(unit) + "')");
            }
        }
        typeArgs.add(refinedProducedType);
    }
    return typeArgs;
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) LazyType(org.eclipse.ceylon.model.typechecker.model.LazyType) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.erasedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.erasedType) SiteVariance(org.eclipse.ceylon.model.typechecker.model.SiteVariance) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Unit(org.eclipse.ceylon.model.typechecker.model.Unit) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 73 with TypeParameter

use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.

the class RefinementVisitor method createRefiningParameterList.

private void createRefiningParameterList(Reference rm, Function method, Tree.ParameterList params, Unit unit, Map<TypeParameter, Type> subs, ParameterList pl) {
    ParameterList list = new ParameterList();
    int j = 0;
    for (Parameter p : pl.getParameters()) {
        // TODO: meaningful errors when parameters don't line up
        // currently this is handled elsewhere, but we can
        // probably do it better right here
        createRefiningParameter(rm, method, p, list, params, j++, subs, unit);
    }
    method.getParameterLists().add(list);
}
Also used : ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter)

Example 74 with TypeParameter

use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.

the class TypeArgumentInference method getInferredTypeArgsForTypeConstructor.

/**
 * Infer type arguments for a generic function reference
 * that occurs within the primary of an invocation
 * expression.
 *
 * @param that the invocation
 * @param receiverType the qualifying type
 * @param type the type constructor
 * @param typeParameters the type parameters to infer
 *
 * @return the type arguments
 */
List<Type> getInferredTypeArgsForTypeConstructor(Tree.InvocationExpression that, Type receiverType, Type type, List<TypeParameter> typeParameters) {
    Tree.PositionalArgumentList pal = that.getPositionalArgumentList();
    if (pal == null) {
        return null;
    } else {
        List<Type> typeArguments = new ArrayList<Type>();
        for (TypeParameter tp : typeParameters) {
            List<Type> paramTypes = unit.getCallableArgumentTypes(type);
            Type paramTypesAsTuple = unit.getCallableTuple(type);
            boolean sequenced = unit.isTupleLengthUnbounded(paramTypesAsTuple);
            int argCount = pal.getPositionalArguments().size();
            boolean findUpperBounds = isEffectivelyContravariant(tp, type, argCount);
            Type it = inferTypeArgumentFromPositionalArgs(tp, paramTypes, paramTypesAsTuple, sequenced, receiverType, pal, findUpperBounds);
            typeArguments.add(it);
        }
        // TODO: apply type constraints!!
        return typeArguments;
    }
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) ArrayList(java.util.ArrayList) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Example 75 with TypeParameter

use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.

the class TypeArgumentInference method getInferredTypeArgsForStaticReference.

/**
 * Infer type arguments for the qualifying type in a
 * static method reference that is directly invoked.
 * This method does not correctly handle stuff like
 * constructors or Java static methods.
 *
 * @param that the invocation
 * @param type the type whose type arguments we're
 *             inferring (the qualifying type)
 * @param receiverType
 */
List<Type> getInferredTypeArgsForStaticReference(Tree.InvocationExpression that, TypeDeclaration type, Type receiverType, Tree.MemberOrTypeExpression primary) {
    Tree.PositionalArgumentList pal = that.getPositionalArgumentList();
    Declaration invoked = primary.getDeclaration();
    if (pal == null) {
        return null;
    } else {
        if (invoked instanceof Functional) {
            List<PositionalArgument> args = pal.getPositionalArguments();
            Functional fun = (Functional) invoked;
            List<ParameterList> parameterLists = fun.getParameterLists();
            if (args.isEmpty() || parameterLists.isEmpty()) {
                return null;
            } else {
                // a static method ref invocation has exactly
                // one meaningful argument (the instance of
                // the receiving type)
                Tree.PositionalArgument arg = args.get(0);
                if (arg == null) {
                    return null;
                } else {
                    Type at = arg.getTypeModel();
                    Type tt = type.getType();
                    List<TypeParameter> typeParams = type.getTypeParameters();
                    List<Type> typeArgs = new ArrayList<Type>(typeParams.size());
                    for (TypeParameter tp : typeParams) {
                        Type it = inferTypeArg(tp, tt, at, // TODO: is this 100% correct?
                        false, arg);
                        if (it == null || it.containsUnknowns()) {
                            that.addError("could not infer type argument from given arguments: type parameter '" + tp.getName() + "' could not be inferred");
                        }
                        typeArgs.add(it);
                    }
                    return constrainInferredTypes(typeParams, typeArgs, receiverType, invoked);
                }
            }
        } else {
            return null;
        }
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) ArrayList(java.util.ArrayList) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Aggregations

TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)181 Type (org.eclipse.ceylon.model.typechecker.model.Type)138 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)82 ArrayList (java.util.ArrayList)57 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)57 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)54 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)46 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)45 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)35 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)32 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)30 Function (org.eclipse.ceylon.model.typechecker.model.Function)29 AnalyzerUtil.getTupleType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType)28 AnalyzerUtil.spreadType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType)28 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)28 IntersectionType (org.eclipse.ceylon.model.typechecker.model.IntersectionType)27 JCTypeParameter (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter)26 Class (org.eclipse.ceylon.model.typechecker.model.Class)26 UnionType (org.eclipse.ceylon.model.typechecker.model.UnionType)25 HashMap (java.util.HashMap)24