Search in sources :

Example 31 with Type

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

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)) {
        // simple case
        if (type.getUnderlyingType() == null && refinedDeclaration.getType() != null) {
            if (type.isCached()) {
                type = type.clone();
            }
            type.setUnderlyingType(refinedDeclaration.getType().getUnderlyingType());
            declaration.setType(type);
        }
        // special case for variadics
        if (Decl.isValueParameter(refinedDeclaration)) {
            Parameter parameter = ((FunctionOrValue) refinedDeclaration).getInitializerParameter();
            if (parameter.isSequenced()) {
                // inherit the underlying type of the iterated type
                Type refinedIteratedType = refinedDeclaration.getType().getTypeArgumentList().get(0);
                if (refinedIteratedType.getUnderlyingType() != null) {
                    Type ourIteratedType = type.getTypeArgumentList().get(0);
                    if (ourIteratedType.getUnderlyingType() == null) {
                        if (ourIteratedType.isCached()) {
                            ourIteratedType = ourIteratedType.clone();
                        }
                        ourIteratedType.setUnderlyingType(refinedIteratedType.getUnderlyingType());
                        type.getTypeArgumentList().set(0, ourIteratedType);
                        // make sure we remove those types from the cache otherwise UGLY things happen
                        TypeCache cache = type.getDeclaration().getUnit().getCache();
                        if (cache != null) {
                            cache.remove(ourIteratedType);
                            cache.remove(type);
                        }
                    }
                }
            }
        }
    }
    // 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 && 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);
        // until it's used later by user code
        if (declaration.getOriginalDeclaration() != null && declaration.hasUncheckedNullType())
            unbox = false;
        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(org.eclipse.ceylon.model.typechecker.model.Functional) Function(org.eclipse.ceylon.model.typechecker.model.Function) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AbstractTransformer.isPinnedType(org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.isPinnedType) Type(org.eclipse.ceylon.model.typechecker.model.Type) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypeCache(org.eclipse.ceylon.model.typechecker.context.TypeCache) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) FunctionalParameterDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.FunctionalParameterDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) AttributeDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 32 with Type

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

the class BoxingDeclarationVisitor method setErasureState.

private void setErasureState(TypedDeclaration decl) {
    // deal with invalid input
    if (decl == null)
        return;
    Type type = decl.getType();
    boolean erased = false;
    boolean untrusted = false;
    if (type != null) {
        if (hasErasure(type) || hasSubstitutedBounds(type) || type.isTypeConstructor()) {
            erased = true;
        }
        if (decl.isActual() && decl.getContainer() instanceof ClassOrInterface) {
            TypedDeclaration refinedDeclaration = getRefinedDeclarationForWideningRules(decl);
            if (refinedDeclaration != null && refinedDeclaration != decl && decl.getUntrustedType() == null) {
                // make sure the refined decl is set before we look at it
                setErasureState(refinedDeclaration);
            }
            // make sure we did not lose type information due to non-widening
            if (isWideningTypedDeclaration(decl)) {
                // widening means not trusting the type, otherwise we end up thinking that the type is
                // something it's not and regular erasure rules don't apply there
                untrusted = true;
                erased = true;
            }
        }
    }
    decl.setTypeErased(erased);
    if (isPinnedType(decl)) {
        untrusted = true;
    }
    decl.setUntrustedType(untrusted);
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AbstractTransformer.isPinnedType(org.eclipse.ceylon.compiler.java.codegen.AbstractTransformer.isPinnedType) Type(org.eclipse.ceylon.model.typechecker.model.Type)

Example 33 with Type

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

the class BoxingVisitor method visit.

@Override
public void visit(IndexExpression that) {
    super.visit(that);
    // we need to propagate from the underlying method call (item/span)
    if (that.getPrimary() == null || that.getPrimary().getTypeModel() == null)
        return;
    Type lhsModel = that.getPrimary().getTypeModel();
    if (lhsModel.getDeclaration() == null)
        return;
    String methodName = that.getElementOrRange() instanceof Tree.Element ? "get" : "span";
    // find the method from its declaration
    TypedDeclaration member = (TypedDeclaration) lhsModel.getDeclaration().getMember(methodName, null, false);
    if (member == null)
        return;
    propagateFromDeclaration(that, member);
    // also copy the underlying type, mostly useful for java primitive arrays
    if (member.getType().getUnderlyingType() != null) {
        Type type = that.getTypeModel();
        if (type.isCached())
            type = type.clone();
        type.setUnderlyingType(member.getType().getUnderlyingType());
        that.setTypeModel(type);
    }
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Type(org.eclipse.ceylon.model.typechecker.model.Type) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Example 34 with Type

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

the class BoxingVisitor method hasTypeParameterWithConstraintsOutsideScopeResolved.

private boolean hasTypeParameterWithConstraintsOutsideScopeResolved(Type type, Scope scope) {
    if (type == null)
        return false;
    if (type.isUnion()) {
        java.util.List<Type> caseTypes = type.getCaseTypes();
        for (Type pt : caseTypes) {
            if (hasTypeParameterWithConstraintsOutsideScopeResolved(pt, scope))
                return true;
        }
        return false;
    }
    if (type.isIntersection()) {
        java.util.List<Type> satisfiedTypes = type.getSatisfiedTypes();
        for (Type pt : satisfiedTypes) {
            if (hasTypeParameterWithConstraintsOutsideScopeResolved(pt, scope))
                return true;
        }
        return false;
    }
    TypeDeclaration declaration = type.getDeclaration();
    if (declaration == null)
        return false;
    if (type.isTypeParameter()) {
        // only look at it if it is defined outside our scope
        Scope typeParameterScope = declaration.getContainer();
        while (scope != null) {
            if (Decl.equalScopes(scope, typeParameterScope))
                return false;
            scope = scope.getContainer();
        }
        TypeParameter tp = (TypeParameter) declaration;
        Boolean nonErasedBounds = tp.hasNonErasedBounds();
        if (nonErasedBounds == null)
            visitTypeParameter(tp);
        return nonErasedBounds != null ? nonErasedBounds.booleanValue() : false;
    }
    // now check its type parameters
    for (Type pt : type.getTypeArgumentList()) {
        if (hasTypeParameterWithConstraintsOutsideScopeResolved(pt, scope))
            return true;
    }
    // no problem here
    return false;
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 35 with Type

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

the class BoxingVisitor method visit.

@Override
public void visit(QualifiedMemberExpression that) {
    super.visit(that);
    // handle errors gracefully
    if (that.getDeclaration() == null)
        return;
    if (that.getMemberOperator() instanceof Tree.SafeMemberOp) {
        TypedDeclaration decl = (TypedDeclaration) that.getDeclaration();
        if (CodegenUtil.isRaw(decl))
            CodegenUtil.markRaw(that);
        if (CodegenUtil.hasTypeErased(decl))
            CodegenUtil.markTypeErased(that);
        if (CodegenUtil.hasUntrustedType(decl) || hasTypeParameterWithConstraintsOutsideScope(decl.getType(), that.getScope()))
            CodegenUtil.markUntrustedType(that);
    // we must be boxed, since safe member op "?." returns an optional type
    // return;
    } else if (that.getMemberOperator() instanceof Tree.MemberOp && Decl.isValueTypeDecl(that.getPrimary()) && CodegenUtil.isUnBoxed(that.getPrimary())) {
        // it's unboxed if it's an unboxable type or it's declared void
        if (Decl.isValueTypeDecl((TypedDeclaration) that.getDeclaration()) || (that.getDeclaration() instanceof Function && ((Function) that.getDeclaration()).isDeclaredVoid()))
            CodegenUtil.markUnBoxed(that);
        if (CodegenUtil.isRaw((TypedDeclaration) that.getDeclaration()))
            CodegenUtil.markRaw(that);
        if (CodegenUtil.hasTypeErased((TypedDeclaration) that.getDeclaration()))
            CodegenUtil.markTypeErased(that);
    } else {
        propagateFromDeclaration(that, (TypedDeclaration) that.getDeclaration());
    }
    // be (ex: <String>), and in that case we will generate a proper Sequential<String> which is not raw at all
    if (that.getMemberOperator() instanceof Tree.SpreadOp) {
        // find the return element type
        Type elementType = that.getTarget().getType();
        CodegenUtil.markTypeErased(that, hasErasure(elementType));
    }
    if (ExpressionTransformer.isSuperOrSuperOf(that.getPrimary())) {
        // if the target is an interface whose type arguments have been turned to raw, make this expression
        // as erased
        Reference target = that.getTarget();
        if (target != null && target.getQualifyingType() != null && target.getQualifyingType().getDeclaration() instanceof Interface) {
            if (isRaw(target.getQualifyingType())) {
                CodegenUtil.markTypeErased(that);
            } else // See note in ClassTransformer.makeDelegateToCompanion for a similar test
            {
                TypeDeclaration declaration = target.getQualifyingType().getDeclaration();
                if (needsRawCastForMixinSuperCall(declaration, target.getType()))
                    CodegenUtil.markTypeErased(that);
            }
        }
    }
    Type primaryType;
    if (that.getPrimary() instanceof Tree.Package || that.getTarget() == null) {
        primaryType = that.getPrimary().getTypeModel();
    } else {
        primaryType = that.getTarget().getQualifyingType();
    }
    if (primaryType != null && (isRaw(primaryType) || willEraseToSequence(primaryType)) && that.getTarget() != null && that.getTarget().getDeclaration() instanceof TypedDeclaration && CodegenUtil.containsTypeParameter(((TypedDeclaration) that.getTarget().getDeclaration()).getType())) {
        CodegenUtil.markTypeErased(that);
    }
    if (isRaw(primaryType) && that.getTypeModel().getDeclaration().isParameterized()) {
        CodegenUtil.markRaw(that);
    }
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Function(org.eclipse.ceylon.model.typechecker.model.Function) Type(org.eclipse.ceylon.model.typechecker.model.Type) Reference(org.eclipse.ceylon.model.typechecker.model.Reference) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Interface(org.eclipse.ceylon.model.typechecker.model.Interface)

Aggregations

Type (org.eclipse.ceylon.model.typechecker.model.Type)692 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)270 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)263 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)244 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)225 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)207 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)182 AnalyzerUtil.getTupleType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType)176 AnalyzerUtil.spreadType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType)176 ModelUtil.unionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType)169 ModelUtil.genericFunctionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType)153 UnionType (org.eclipse.ceylon.model.typechecker.model.UnionType)130 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)125 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)114 ArrayList (java.util.ArrayList)106 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)100 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)96 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)95 IntersectionType (org.eclipse.ceylon.model.typechecker.model.IntersectionType)94 Class (org.eclipse.ceylon.model.typechecker.model.Class)87