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;
}
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);
}
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());
}
}
}
}
}
}
}
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);
}
}
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);
}
Aggregations