Search in sources :

Example 41 with TypeParameter

use of com.redhat.ceylon.model.typechecker.model.TypeParameter in project ceylon-compiler by ceylon.

the class AbstractTransformer method declarationAppearsInInvariantPosition.

private boolean declarationAppearsInInvariantPosition(TypeDeclaration declaration, Type type) {
    if (type.isUnion()) {
        for (Type pt : type.getCaseTypes()) {
            if (declarationAppearsInInvariantPosition(declaration, pt))
                return true;
        }
        return false;
    }
    if (type.isIntersection()) {
        for (Type pt : type.getSatisfiedTypes()) {
            if (declarationAppearsInInvariantPosition(declaration, pt))
                return true;
        }
        return false;
    }
    if (type.isClassOrInterface()) {
        TypeDeclaration typeDeclaration = type.getDeclaration();
        java.util.List<TypeParameter> typeParameters = typeDeclaration.getTypeParameters();
        Map<TypeParameter, Type> typeArguments = type.getTypeArguments();
        for (TypeParameter tp : typeParameters) {
            Type typeArgument = typeArguments.get(tp);
            if (tp.isInvariant() || hasDependentTypeParameters(typeParameters, tp)) {
                if (Decl.equal(typeArgument.getDeclaration(), declaration)) {
                    return true;
                }
            }
            if (declarationAppearsInInvariantPosition(declaration, typeArgument))
                return true;
        }
    }
    return false;
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 42 with TypeParameter

use of com.redhat.ceylon.model.typechecker.model.TypeParameter in project ceylon-compiler by ceylon.

the class AbstractTransformer method getRefinedTypedReference.

private TypedReference getRefinedTypedReference(TypedReference typedReference, TypedDeclaration refinedDeclaration) {
    TypeDeclaration refinedContainer = (TypeDeclaration) refinedDeclaration.getContainer();
    Type refinedContainerType = typedReference.getQualifyingType().getSupertype(refinedContainer);
    ArrayList<Type> typeArgs = new ArrayList<Type>();
    if (typedReference.getDeclaration() instanceof Generic) {
        for (TypeParameter tp : ((Generic) typedReference.getDeclaration()).getTypeParameters()) {
            typeArgs.add(typedReference.getTypeArguments().get(tp));
        }
    }
    return refinedDeclaration.appliedTypedReference(refinedContainerType, typeArgs);
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) Generic(com.redhat.ceylon.model.typechecker.model.Generic) ArrayList(java.util.ArrayList) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 43 with TypeParameter

use of com.redhat.ceylon.model.typechecker.model.TypeParameter in project ceylon-compiler by ceylon.

the class AbstractTransformer method collectQualifyingTypeArguments.

/**
     * Collects all the type parameters and arguments required for an interface that's been pulled up to the
     * toplevel, including its containing type and method type parameters.
     */
private void collectQualifyingTypeArguments(java.util.List<TypeParameter> qualifyingTypeParameters, Map<TypeParameter, Type> qualifyingTypeArguments, java.util.List<Reference> qualifyingTypes) {
    // make sure we only add type parameters with the same name once, as duplicates are erased from the target interface
    // since they cannot be accessed
    Set<String> names = new HashSet<String>();
    // walk the qualifying types backwards to make sure we only add a TP with the same name once and the outer one wins
    for (int i = qualifyingTypes.size() - 1; i >= 0; i--) {
        Reference qualifiedType = qualifyingTypes.get(i);
        Map<TypeParameter, Type> tas = qualifiedType.getTypeArguments();
        java.util.List<TypeParameter> tps = ((Generic) qualifiedType.getDeclaration()).getTypeParameters();
        // add any type params for this type
        if (tps != null) {
            int index = 0;
            for (TypeParameter tp : tps) {
                // add it only once
                if (names.add(tp.getName())) {
                    // start putting all these type parameters at 0 and then in order
                    // so that outer type params end up before inner type params but
                    // order is preserved within each type
                    qualifyingTypeParameters.add(index++, tp);
                    qualifyingTypeArguments.put(tp, tas.get(tp));
                }
            }
        }
        // add any container method TP
        Declaration declaration = qualifiedType.getDeclaration();
        if (Decl.isLocal(declaration)) {
            Scope scope = declaration.getContainer();
            // collect every container method until the next type or package
            java.util.List<Function> methods = new LinkedList<Function>();
            while (scope != null && scope instanceof ClassOrInterface == false && scope instanceof Package == false) {
                if (scope instanceof Function) {
                    methods.add((Function) scope);
                }
                scope = scope.getContainer();
            }
            // methods are sorted inner to outer, which is the order we're following here for types
            for (Function method : methods) {
                java.util.List<TypeParameter> methodTypeParameters = method.getTypeParameters();
                if (methodTypeParameters != null) {
                    int index = 0;
                    for (TypeParameter tp : methodTypeParameters) {
                        // add it only once
                        if (names.add(tp.getName())) {
                            // start putting all these type parameters at 0 and then in order
                            // so that outer type params end up before inner type params but
                            // order is preserved within each type
                            qualifyingTypeParameters.add(index++, tp);
                            qualifyingTypeArguments.put(tp, tp.getType());
                        }
                    }
                }
            }
        }
    }
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) Reference(com.redhat.ceylon.model.typechecker.model.Reference) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) Generic(com.redhat.ceylon.model.typechecker.model.Generic) LinkedList(java.util.LinkedList) Function(com.redhat.ceylon.model.typechecker.model.Function) Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) Scope(com.redhat.ceylon.model.typechecker.model.Scope) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) Package(com.redhat.ceylon.model.typechecker.model.Package) HashSet(java.util.HashSet)

Example 44 with TypeParameter

use of com.redhat.ceylon.model.typechecker.model.TypeParameter in project ceylon-compiler by ceylon.

the class AbstractTransformer method makeTypeTest.

private <R> R makeTypeTest(TypeTestTransformation<R> typeTester, JCExpression firstTimeExpr, Naming.CName varName, Type testedType, Type expressionType) {
    R result = null;
    // make sure aliases are resolved
    testedType = testedType.resolveAliases();
    // optimisation when all we're doing is making sure it is not null
    if (expressionType != null && testedType.getSupertype(typeFact().getObjectDeclaration()) != null && expressionType.isExactly(typeFact().getOptionalType(testedType))) {
        JCExpression varExpr = firstTimeExpr != null ? firstTimeExpr : varName.makeIdent();
        return typeTester.nullTest(varExpr, JCTree.NE);
    }
    TypeDeclaration declaration = testedType.getDeclaration();
    if (declaration instanceof ClassOrInterface) {
        JCExpression varExpr = firstTimeExpr != null ? firstTimeExpr : varName.makeIdent();
        if (isAnything(testedType)) {
            // everything is Void, it's the root of the hierarchy
            return typeTester.eval(varExpr, true);
        } else if (isNull(testedType)) {
            // is Null => is null
            return typeTester.nullTest(varExpr, JCTree.EQ);
        } else if (testedType.isExactly(typeFact().getObjectType())) {
            // is Object => is not null
            return typeTester.nullTest(varExpr, JCTree.NE);
        } else if (testedType.isExactly(typeFact().getIdentifiableType())) {
            // it's erased
            return typeTester.isIdentifiable(varExpr);
        } else if (testedType.getDeclaration().equals(typeFact().getTrueValueDeclaration().getTypeDeclaration())) {
            return typeTester.isTrue(varExpr);
        } else if (testedType.getDeclaration().equals(typeFact().getFalseValueDeclaration().getTypeDeclaration())) {
            return typeTester.isFalse(varExpr);
        } else if (testedType.isExactly(typeFact().getBasicType())) {
            // it's erased
            return typeTester.isBasic(varExpr);
        } else if (testedType.getDeclaration().getQualifiedNameString().equals("java.lang::Error")) {
            // need to exclude AssertionError
            return typeTester.andOr(typeTester.isInstanceof(varExpr, testedType, expressionType), typeTester.not(typeTester.isInstanceof(varName.makeIdent(), typeFact().getAssertionErrorDeclaration().getType(), expressionType)), JCTree.AND);
        } else if (!hasTypeArguments(testedType)) {
            // non-generic Class or interface, use instanceof
            return typeTester.isInstanceof(varExpr, testedType, expressionType);
        } else {
            // generic class or interface...
            if (declaration.getSelfType() != null && // of TypeArg
            declaration.getSelfType().getDeclaration() instanceof TypeParameter && // given TypeArg satisfies SelfType<TypeArg>
            declaration.getSelfType().isSubtypeOf(declaration.getType())) {
                Type selfTypeArg = testedType.getTypeArguments().get(declaration.getSelfType().getDeclaration());
                if (selfTypeArg.getDeclaration() instanceof ClassOrInterface) {
                    // first check if the type is inhabited or not
                    if (selfTypeArg.getDeclaration().inherits(declaration)) {
                        // "is SelfType<ClassOrInterface>" can be written "is ClassOrInterface" 
                        return makeTypeTest(typeTester, firstTimeExpr, varName, selfTypeArg, expressionType);
                    } else {
                        // always false, for example Comparable<Anything> is uninhabited because Anything does not inherit from Comparable
                        return typeTester.eval(varExpr, false);
                    }
                }
            // if not, keep trying
            }
            if (canOptimiseReifiedTypeTest(testedType)) {
                // Use an instanceof
                return typeTester.isInstanceof(varExpr, testedType, expressionType);
            } else {
                // Have to use a reified test
                if (!Decl.equal(declaration, expressionType.getDeclaration()) && canUseFastFailTypeTest(testedType)) {
                    // instanceof shortcircuit doesn't achieve anything
                    return typeTester.andOr(typeTester.isInstanceof(varExpr, testedType, expressionType), typeTester.isReified(varName.makeIdent(), testedType), JCTree.AND);
                } else {
                    return typeTester.isReified(varExpr, testedType);
                }
            }
        }
    } else if (typeFact().isUnion(testedType)) {
        for (Type pt : testedType.getCaseTypes()) {
            R partExpr = makeTypeTest(typeTester, firstTimeExpr, varName, pt, expressionType);
            firstTimeExpr = null;
            if (result == null) {
                result = partExpr;
            } else {
                result = typeTester.andOr(result, partExpr, JCTree.OR);
            }
        }
        return result;
    } else if (typeFact().isIntersection(testedType)) {
        for (Type pt : testedType.getSatisfiedTypes()) {
            R partExpr = makeTypeTest(typeTester, firstTimeExpr, varName, pt, expressionType);
            firstTimeExpr = null;
            if (result == null) {
                result = partExpr;
            } else {
                result = typeTester.andOr(result, partExpr, JCTree.AND);
            }
        }
        return result;
    } else if (testedType.isNothing()) {
        // nothing is Bottom
        JCExpression varExpr = firstTimeExpr != null ? firstTimeExpr : varName.makeIdent();
        return typeTester.eval(varExpr, false);
    } else if (declaration instanceof TypeParameter) {
        JCExpression varExpr = firstTimeExpr != null ? firstTimeExpr : varName.makeIdent();
        if (!reifiableUpperBounds((TypeParameter) declaration, expressionType).isEmpty()) {
            // If we're testing against a type parameter with  
            // class or interface upper bounds we can again shortcircuit the 
            // Util.isReified() using instanceof against the bounds
            result = typeTester.isReified(varName.makeIdent(), testedType);
            Iterator<Type> iterator = reifiableUpperBounds((TypeParameter) declaration, expressionType).iterator();
            while (iterator.hasNext()) {
                Type type = iterator.next();
                ClassOrInterface c = ((ClassOrInterface) type.resolveAliases().getDeclaration());
                result = typeTester.andOr(typeTester.isInstanceof(iterator.hasNext() ? varName.makeIdent() : varExpr, c.getType(), expressionType), result, JCTree.AND);
            }
            return result;
        } else {
            return typeTester.isReified(varExpr, testedType);
        }
    } else {
        throw BugException.unhandledDeclarationCase(declaration);
    }
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 45 with TypeParameter

use of com.redhat.ceylon.model.typechecker.model.TypeParameter in project ceylon-compiler by ceylon.

the class BoxingDeclarationVisitor method setBoxingState.

private void setBoxingState(TypedDeclaration declaration, TypedDeclaration refinedDeclaration, Node that) {
    Type type = declaration.getType();
    if (type == null) {
        // an error must have already been reported
        return;
    }
    // fetch the real refined declaration if required
    if (Decl.equal(declaration, refinedDeclaration) && declaration instanceof FunctionOrValue && ((FunctionOrValue) declaration).isParameter() && declaration.getContainer() instanceof Class) {
        // maybe it is really inherited from a field?
        FunctionOrValue methodOrValueForParam = (FunctionOrValue) declaration;
        if (methodOrValueForParam != null) {
            // make sure we get the refined version of that member
            refinedDeclaration = (TypedDeclaration) methodOrValueForParam.getRefinedDeclaration();
        }
    }
    // inherit underlying type constraints
    if (!Decl.equal(refinedDeclaration, declaration) && type.getUnderlyingType() == null && refinedDeclaration.getType() != null)
        type.setUnderlyingType(refinedDeclaration.getType().getUnderlyingType());
    // abort if our boxing state has already been set
    if (declaration.getUnboxed() != null)
        return;
    // functional parameter return values are always boxed if we're not creating a method for them
    if (declaration instanceof Function && ((Function) declaration).isParameter() && !JvmBackendUtil.createMethod((Function) declaration)) {
        declaration.setUnboxed(false);
        return;
    }
    if (!Decl.equal(refinedDeclaration, declaration)) {
        // make sure refined declarations have already been set
        if (refinedDeclaration.getUnboxed() == null)
            setBoxingState(refinedDeclaration, refinedDeclaration, that);
        // inherit
        declaration.setUnboxed(refinedDeclaration.getUnboxed());
    } else if (declaration instanceof Function && CodegenUtil.isVoid(declaration.getType()) && Strategy.useBoxedVoid((Function) declaration) && !(refinedDeclaration.getTypeDeclaration() instanceof TypeParameter) && !CodegenUtil.isContainerFunctionalParameter(refinedDeclaration) && !(refinedDeclaration instanceof Functional && Decl.isMpl((Functional) refinedDeclaration))) {
        declaration.setUnboxed(false);
    } else if ((isCeylonBasicType(type) || Decl.isUnboxedVoid(declaration)) && !(refinedDeclaration.getTypeDeclaration() instanceof TypeParameter) && (refinedDeclaration.getContainer() instanceof Declaration == false || !CodegenUtil.isContainerFunctionalParameter(refinedDeclaration)) && !(refinedDeclaration instanceof Functional && Decl.isMpl((Functional) refinedDeclaration))) {
        boolean unbox = !forceBoxedLocals || !(declaration instanceof Value) || !Decl.isLocal(declaration) || Decl.isParameter(declaration) || Decl.isTransient(declaration);
        declaration.setUnboxed(unbox);
    } else if (Decl.isValueParameter(declaration) && CodegenUtil.isContainerFunctionalParameter(declaration) && JvmBackendUtil.createMethod((FunctionOrValue) declaration.getContainer())) {
        Function functionalParameter = (Function) declaration.getContainer();
        TypedDeclaration refinedFrom = (TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(functionalParameter, optimisedMethodSpecifiersToMethods);
        if (Decl.equal(refinedFrom, functionalParameter)) {
            // not a method return type (where void would be considered unboxed).
            if (declaration.getUnit().getAnythingType().isExactly(declaration.getType()) || declaration.getUnit().isOptionalType(declaration.getType())) {
                declaration.setUnboxed(false);
            } else {
                declaration.setUnboxed(true);
            }
        } else {
            // make sure refined declarations have already been set
            if (refinedFrom.getUnboxed() == null)
                setBoxingState(refinedFrom, refinedFrom, that);
            // inherit
            declaration.setUnboxed(refinedFrom.getUnboxed());
        }
    } else {
        declaration.setUnboxed(false);
    }
    // Any "@boxed" or "@unboxed" compiler annotation overrides
    boxFromAnnotation(declaration, that);
}
Also used : Functional(com.redhat.ceylon.model.typechecker.model.Functional) Function(com.redhat.ceylon.model.typechecker.model.Function) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Type(com.redhat.ceylon.model.typechecker.model.Type) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) Value(com.redhat.ceylon.model.typechecker.model.Value) Class(com.redhat.ceylon.model.typechecker.model.Class) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) FunctionalParameterDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionalParameterDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue)

Aggregations

TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)59 Type (com.redhat.ceylon.model.typechecker.model.Type)40 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)24 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)23 ModelUtil.appliedType (com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType)21 ArrayList (java.util.ArrayList)15 Function (com.redhat.ceylon.model.typechecker.model.Function)14 Class (com.redhat.ceylon.model.typechecker.model.Class)13 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)13 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)13 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)13 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)12 TypedReference (com.redhat.ceylon.model.typechecker.model.TypedReference)12 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)12 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)10 Generic (com.redhat.ceylon.model.typechecker.model.Generic)9 Constructor (com.redhat.ceylon.model.typechecker.model.Constructor)8 Interface (com.redhat.ceylon.model.typechecker.model.Interface)8 ParameterList (com.redhat.ceylon.model.typechecker.model.ParameterList)8 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)7