Search in sources :

Example 86 with TypeParameter

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

the class TypeArgumentInference method constrainInferredTypes.

private List<Type> constrainInferredTypes(List<TypeParameter> typeParameters, List<Type> inferredTypeArgs, Type qualifyingType, Declaration declaration) {
    int size = inferredTypeArgs.size();
    boolean found = false;
    for (int i = 0; i < size; i++) {
        TypeParameter tp = typeParameters.get(i);
        // if (!tp.isCovariant()) {
        List<Type> bounds = tp.getSatisfiedTypes();
        if (!bounds.isEmpty()) {
            found = true;
        }
    // }
    }
    if (found) {
        Reference ref;
        if (declaration instanceof Value) {
            Value value = (Value) declaration;
            if (value.getType().isTypeConstructor()) {
                if (qualifyingType == null) {
                    ref = declaration.appliedReference(null, NO_TYPE_ARGS);
                } else {
                    ref = qualifyingType.getTypedReference(declaration, NO_TYPE_ARGS);
                }
                TypeDeclaration dec = ref.getType().getDeclaration();
                ref = dec.appliedReference(null, inferredTypeArgs);
            } else {
                return inferredTypeArgs;
            }
        } else {
            if (qualifyingType == null) {
                ref = declaration.appliedReference(null, inferredTypeArgs);
            } else {
                ref = qualifyingType.getTypedReference(declaration, inferredTypeArgs);
            }
        }
        Map<TypeParameter, Type> args = ref.getTypeArguments();
        ArrayList<Type> result = new ArrayList<Type>(size);
        for (int i = 0; i < size; i++) {
            TypeParameter tp = typeParameters.get(i);
            Type arg = inferredTypeArgs.get(i);
            Type constrainedArg = // tp.isCovariant() ? arg :
            constrainInferredType(tp, arg, args);
            result.add(constrainedArg);
        }
        return result;
    } else {
        return inferredTypeArgs;
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) 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) Reference(org.eclipse.ceylon.model.typechecker.model.Reference) TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) ArrayList(java.util.ArrayList) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 87 with TypeParameter

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

the class TypeVisitor method visit.

@Override
public void visit(Tree.SatisfiedTypes that) {
    super.visit(that);
    TypeDeclaration td = (TypeDeclaration) that.getScope();
    if (td.isAlias()) {
        return;
    }
    List<Tree.StaticType> types = that.getTypes();
    List<Type> list = new ArrayList<Type>(types.size());
    if (types.isEmpty()) {
        that.addError("missing types in satisfies");
    }
    boolean foundTypeParam = false;
    boolean foundClass = false;
    boolean foundInterface = false;
    for (Tree.StaticType st : types) {
        inheritedType(st);
        Type type = st.getTypeModel();
        if (type != null) {
            TypeDeclaration std = type.getDeclaration();
            if (std != null && !(std instanceof UnknownType)) {
                if (std == td) {
                // unnecessary, handled by SupertypeVisitor
                // st.addError("directly extends itself: '" +
                // td.getName() + "'");
                } else if (std instanceof NothingType) {
                    st.addError("satisfies the bottom type 'Nothing'");
                } else if (std instanceof TypeAlias) {
                    st.addError("satisfies a type alias: '" + type.getDeclaration().getName(unit) + "'");
                } else if (std instanceof Constructor) {
                // nothing to do
                } else if (td instanceof TypeParameter) {
                    if (foundTypeParam) {
                        st.addUnsupportedError("type parameter upper bounds are not yet supported in combination with other bounds");
                    } else if (std instanceof TypeParameter) {
                        if (foundClass || foundInterface) {
                            st.addUnsupportedError("type parameter upper bounds are not yet supported in combination with other bounds");
                        }
                        foundTypeParam = true;
                        list.add(type);
                    } else if (std instanceof Class) {
                        if (foundClass) {
                            st.addUnsupportedError("multiple class upper bounds are not yet supported");
                        }
                        foundClass = true;
                        list.add(type);
                    } else if (std instanceof Interface) {
                        foundInterface = true;
                        list.add(type);
                    } else {
                        st.addError("upper bound must be a class, interface, or type parameter");
                    }
                } else {
                    if (std instanceof TypeParameter) {
                        st.addError("directly satisfies type parameter: '" + std.getName(unit) + "'");
                    } else if (std instanceof Class) {
                        st.addError("satisfies a class: '" + std.getName(unit) + "'");
                    } else if (std instanceof Interface) {
                        if (td.isDynamic() && !std.isDynamic()) {
                            st.addError("dynamic interface satisfies a non-dynamic interface: '" + std.getName(unit) + "'");
                        } else {
                            list.add(type);
                        }
                    } else {
                        st.addError("satisfied type must be an interface");
                    }
                }
            }
        }
    }
    td.setSatisfiedTypes(list);
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) AnalyzerUtil.setTypeConstructor(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.setTypeConstructor) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) AnalyzerUtil.unwrapAliasedTypeConstructor(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.unwrapAliasedTypeConstructor) ArrayList(java.util.ArrayList) TypeAlias(org.eclipse.ceylon.model.typechecker.model.TypeAlias) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Class(org.eclipse.ceylon.model.typechecker.model.Class) AnalyzerUtil.isVeryAbstractClass(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.isVeryAbstractClass) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) ModelUtil.getContainingClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getContainingClassOrInterface) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)

Example 88 with TypeParameter

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

the class TypeVisitor method visit.

@Override
public void visit(Tree.TypeParameterList that) {
    super.visit(that);
    List<Tree.TypeParameterDeclaration> tpds = that.getTypeParameterDeclarations();
    List<TypeParameter> params = new ArrayList<TypeParameter>(tpds.size());
    for (int i = tpds.size() - 1; i >= 0; i--) {
        Tree.TypeParameterDeclaration tpd = tpds.get(i);
        if (tpd != null) {
            TypeParameter tp = tpd.getDeclarationModel();
            Type dta = tp.getDefaultTypeArgument();
            if (dta != null) {
                params.add(tp);
                if (dta.involvesTypeParameters(params)) {
                    tpd.getTypeSpecifier().addError("default type argument involves a type parameter not yet declared");
                }
            }
        }
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) ArrayList(java.util.ArrayList) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Example 89 with TypeParameter

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

the class TypeVisitor method visit.

/*@Override 
    public void visit(Tree.TypeConstraint that) {
        super.visit(that);
        if (that.getSelfType()!=null) {
            TypeDeclaration td = (TypeDeclaration) that.getSelfType().getScope();
            TypeParameter tp = that.getDeclarationModel();
            td.setSelfType(tp.getType());
            if (tp.isSelfType()) {
                that.addError("type parameter may not act as self type for two different types");
            }
            else {
                tp.setSelfTypedDeclaration(td);
            }
        }
    }*/
@Override
public void visit(Tree.CaseTypes that) {
    super.visit(that);
    TypeDeclaration td = (TypeDeclaration) that.getScope();
    List<Tree.StaticMemberOrTypeExpression> bmes = that.getBaseMemberExpressions();
    List<Tree.StaticType> cts = that.getTypes();
    List<TypedDeclaration> caseValues = new ArrayList<TypedDeclaration>(bmes.size());
    List<Type> caseTypes = new ArrayList<Type>(bmes.size() + cts.size());
    if (td instanceof TypeParameter) {
        if (!bmes.isEmpty()) {
            that.addError("cases of type parameter must be a types");
        }
    } else {
        for (Tree.StaticMemberOrTypeExpression bme : bmes) {
            // bmes have not yet been resolved
            String name = name(bme.getIdentifier());
            TypedDeclaration od = bme instanceof Tree.BaseMemberExpression ? getTypedDeclaration(bme.getScope(), name, null, false, unit) : getPackageTypedDeclaration(name, null, false, unit);
            if (od != null) {
                caseValues.add(od);
                Type type = od.getType();
                if (type != null) {
                    caseTypes.add(type);
                }
            }
        }
    }
    for (Tree.StaticType ct : cts) {
        inheritedType(ct);
        Type type = ct.getTypeModel();
        if (!isTypeUnknown(type)) {
            if (type.isUnion() || type.isIntersection() || type.isNothing()) {
                // union/intersection types don't have equals()
                if (td instanceof TypeParameter) {
                    ct.addError("enumerated bound must be a class or interface type");
                } else {
                    ct.addError("case type must be a class, interface, or self type");
                }
            } else {
                TypeDeclaration ctd = type.getDeclaration();
                if (ctd.equals(td)) {
                    ct.addError("directly enumerates itself: '" + td.getName() + "'");
                } else if (type.isClassOrInterface()) {
                    caseTypes.add(type);
                } else if (type.isTypeParameter()) {
                    if (td instanceof TypeParameter) {
                        caseTypes.add(type);
                    } else {
                        TypeParameter tp = (TypeParameter) ctd;
                        td.setSelfType(type);
                        if (tp.isSelfType()) {
                            ct.addError("type parameter may not act as self type for two different types");
                        } else {
                            tp.setSelfTypedDeclaration(td);
                            caseTypes.add(type);
                        }
                        if (cts.size() > 1) {
                            ct.addError("a type may not have more than one self type");
                        }
                    }
                } else {
                    if (td instanceof TypeParameter) {
                        ct.addError("enumerated bound must be a class or interface type");
                    } else {
                        ct.addError("case type must be a class, interface, or self type");
                    }
                }
            }
        }
    }
    if (!caseTypes.isEmpty()) {
        TypeDeclaration first = caseTypes.get(0).getDeclaration();
        if (caseTypes.size() == 1 && first.isSelfType()) {
            // for a type family, the type that declares
            // the type parameter may not be the same
            // type for which it acts as a self type
            Scope scope = first.getContainer();
            if (scope instanceof ClassOrInterface) {
                ClassOrInterface ci = (ClassOrInterface) scope;
                if (!ci.isAbstract()) {
                    Tree.StaticType ct = cts.get(0);
                    if (ci.equals(td)) {
                        ct.addError("concrete class parameterized by self type: '" + ci.getName() + "' is not abstract but has the self type '" + first.getName() + "' (make '" + ci.getName() + "' abstract)", 905);
                    } else {
                        // type family
                        ct.addError("concrete class parameterized by self type: '" + ci.getName() + "' is not abstract but declares the self type '" + first.getName() + "' of '" + td.getName() + "' (make '" + ci.getName() + "' abstract)", 905);
                    }
                }
            }
        } else {
            if (td instanceof ClassOrInterface) {
                ClassOrInterface ci = (ClassOrInterface) td;
                if (!ci.isAbstract()) {
                    Class c = (Class) ci;
                    if (!c.hasEnumerated()) {
                        that.addError("concrete class has enumerated subtypes: " + "enumerated class '" + ci.getName() + "' is not abstract" + " (make '" + ci.getName() + "' abstract)", 905);
                    }
                }
            }
        }
        td.setCaseTypes(caseTypes);
        td.setCaseValues(caseValues);
    }
}
Also used : AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) ModelUtil.getContainingClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getContainingClassOrInterface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) ArrayList(java.util.ArrayList) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Class(org.eclipse.ceylon.model.typechecker.model.Class) AnalyzerUtil.isVeryAbstractClass(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.isVeryAbstractClass) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)

Example 90 with TypeParameter

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

the class TypeVisitor method visitSimpleType.

private void visitSimpleType(Tree.SimpleType that, Type ot, TypeDeclaration dec) {
    if (dec instanceof Constructor && // is allowed
    !inTypeLiteral && // constructor is allowed
    !inExtendsOrClassAlias && !inDelegatedConstructor) {
        that.addError("constructor is not a type: '" + dec.getName(unit) + "' is a constructor");
    }
    Tree.TypeArgumentList tal = that.getTypeArgumentList();
    if (tal != null) {
        dec = unwrapAliasedTypeConstructor(dec);
    }
    List<TypeParameter> params = dec.getTypeParameters();
    List<Type> typeArgs = getTypeArguments(tal, ot, params);
    // Note: we actually *check* these type arguments
    // later in ExpressionVisitor
    Type pt = dec.appliedType(ot, typeArgs);
    if (tal == null) {
        if (!params.isEmpty()) {
            // For now the only type constructors allowed
            // as the type of a value are type constructors
            // that alias Callable (in future relax this)
            // and interpret *every* type with a missing
            // type argument list as a type constructor
            Interface cd = unit.getCallableDeclaration();
            boolean functionTypeConstructor = dec.isAlias() ? dec.inherits(cd) : dec.equals(cd);
            if (functionTypeConstructor) {
                pt.setTypeConstructor(true);
            }
        }
    } else {
        if (params.isEmpty()) {
            that.addError("type declaration does not accept type arguments: '" + dec.getName(unit) + "' is not a generic type");
        }
        tal.setTypeModels(typeArgs);
        List<Tree.Type> args = tal.getTypes();
        for (int i = 0; i < args.size() && i < params.size(); i++) {
            Tree.Type t = args.get(i);
            if (t instanceof Tree.StaticType) {
                Tree.StaticType st = (Tree.StaticType) t;
                Tree.TypeVariance variance = st.getTypeVariance();
                if (variance != null) {
                    TypeParameter p = params.get(i);
                    String var = variance.getText();
                    if (var.equals("out")) {
                        pt.setVariance(p, OUT);
                    } else if (var.equals("in")) {
                        pt.setVariance(p, IN);
                    }
                    if (!p.isInvariant()) {
                        // Type doesn't yet know
                        // how to reason about *runtime*
                        // instantiations of variant types
                        // since they are effectively
                        // invariant
                        variance.addUnsupportedError("use-site variant instantiation of declaration-site variant types is not supported: type parameter '" + p.getName() + "' of '" + dec.getName(unit) + "' is declared " + (p.isCovariant() ? "covariant" : "contravariant") + " (remove the '" + var + "')");
                    }
                }
            }
        }
    }
    that.setTypeModel(pt);
    that.setDeclarationModel(dec);
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) AnalyzerUtil.setTypeConstructor(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.setTypeConstructor) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) AnalyzerUtil.unwrapAliasedTypeConstructor(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.unwrapAliasedTypeConstructor) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) ModelUtil.getContainingClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getContainingClassOrInterface) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)

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