use of org.eclipse.ceylon.model.typechecker.model.Type in project ceylon by eclipse.
the class AbstractTransformer method getGetterInterfaceType.
Type getGetterInterfaceType(TypedDeclaration attrTypedDecl) {
TypedReference typedRef = getTypedReference(attrTypedDecl);
TypedReference nonWideningTypedRef = nonWideningTypeDecl(typedRef);
Type nonWideningType = nonWideningType(typedRef, nonWideningTypedRef);
Type type;
boolean unboxed = CodegenUtil.isUnBoxed(attrTypedDecl);
if (unboxed && isCeylonBoolean(nonWideningType)) {
type = javacCeylonTypeToProducedType(syms().ceylonGetterBooleanType);
} else if (unboxed && isCeylonInteger(nonWideningType)) {
if (Decl.isSmall(attrTypedDecl)) {
type = javacCeylonTypeToProducedType(syms().ceylonGetterIntType);
} else {
type = javacCeylonTypeToProducedType(syms().ceylonGetterLongType);
}
} else if (unboxed && isCeylonFloat(nonWideningType)) {
if (Decl.isSmall(attrTypedDecl)) {
type = javacCeylonTypeToProducedType(syms().ceylonGetterFloatType);
} else {
type = javacCeylonTypeToProducedType(syms().ceylonGetterDoubleType);
}
} else if (unboxed && isCeylonCharacter(nonWideningType)) {
if (Decl.isSmall(attrTypedDecl)) {
type = javacCeylonTypeToProducedType(syms().ceylonGetterCharType);
} else {
type = javacCeylonTypeToProducedType(syms().ceylonGetterIntType);
}
} else if (unboxed && isCeylonByte(nonWideningType)) {
type = javacCeylonTypeToProducedType(syms().ceylonGetterByteType);
} else {
type = javacCeylonTypeToProducedType(syms().ceylonGetterType);
Type typeArg = nonWideningType;
if (unboxed && isCeylonString(typeArg)) {
typeArg = javacJavaTypeToProducedType(syms().stringType);
}
type = appliedType(type.getDeclaration(), typeArg);
}
return type;
}
use of org.eclipse.ceylon.model.typechecker.model.Type in project ceylon by eclipse.
the class AbstractTransformer method canOptimiseReifiedTypeTest.
/**
* Determine whether we can use a plain {@code instanceof} instead of
* a full {@code Util.isReified()} for a {@code is} test
*/
private boolean canOptimiseReifiedTypeTest(Type type) {
if (isJavaArray(type)) {
if (isJavaObjectArray(type)) {
MultidimensionalArray multiArray = getMultiDimensionalArrayInfo(type);
// we can test, even if not fully reified in Java
return multiArray.type.getDeclaration() instanceof ClassOrInterface;
} else {
// primitive array we can test
return true;
}
}
// we can optimise it if we've got a ClassOrInterface with only Anything type parameters
TypeDeclaration typeDeclaration = type.getDeclaration();
if (typeDeclaration instanceof ClassOrInterface == false)
return false;
for (Entry<TypeParameter, Type> entry : type.getTypeArguments().entrySet()) {
TypeParameter tp = entry.getKey();
// skip type params for qualifying types
if (!tp.getDeclaration().equals(typeDeclaration))
continue;
if (!type.isCovariant(tp)) {
return false;
}
java.util.List<Type> bounds = tp.getSatisfiedTypes();
Type ta = entry.getValue();
if ((bounds == null || bounds.isEmpty()) && !isAnything(ta)) {
return false;
}
for (Type bound : bounds) {
if (!ta.isSupertypeOf(bound)) {
return false;
}
}
}
// they're all Anything (or supertypes of their upper bound) we can optimise, unless we have a container with type arguments
Type qualifyingType = type.getQualifyingType();
if (qualifyingType == null && // ignore qualifying types of static java declarations
(ModelUtil.isCeylonDeclaration(type.getDeclaration()) || !type.getDeclaration().isStatic())) {
Declaration declaration = type.getDeclaration();
do {
// it may be contained in a function or value, and we want its type
Declaration enclosingDeclaration = getDeclarationContainer(declaration);
if (enclosingDeclaration instanceof TypedDeclaration) {
// must be in scope
if (enclosingDeclaration.isParameterized())
return false;
// look up the containers
declaration = enclosingDeclaration;
} else if (enclosingDeclaration instanceof TypeDeclaration) {
// we can't optimise if that container has type arguments as they are not provided
if (enclosingDeclaration.isParameterized())
return false;
// look up the containers
declaration = enclosingDeclaration;
} else {
// that's fucked up
break;
}
// go up every containing typed declaration
} while (declaration != null);
// we can optimise!
return true;
} else if (qualifyingType != null) {
// we can only optimise if the qualifying type can also be optimised
return canOptimiseReifiedTypeTest(qualifyingType);
} else {
// we can optimise!
return true;
}
}
use of org.eclipse.ceylon.model.typechecker.model.Type in project ceylon by eclipse.
the class AbstractTransformer method boxJavaType.
JCExpression boxJavaType(JCExpression expr, Type type) {
JCExpression allowNull = make().Literal(!type.isSubtypeOf(typeFact().getObjectType()));
type = simplifyType(type);
if (type.isSubtypeOf(typeFact().getNullType())) {
return expr;
} else if (type.isString()) {
return expr;
} else if (type.getDeclaration().equals(typeFact().getListDeclaration())) {
// Wrappings.toCeylonList().inverse()
Type elementType = type.getTypeArgumentList().get(0);
return make().Apply(null, makeSelect(make().Apply(null, makeSelect(make().Apply(List.<JCExpression>of(isJavaBoxableType(elementType, true) ? javaBoxType(elementType) : makeJavaType(elementType, JT_TYPE_ARGUMENT), makeJavaType(elementType, JT_TYPE_ARGUMENT)), makeQuotedFQIdent("org.eclipse.ceylon.compiler.java.wrapping.Wrappings.toCeylonList"), List.<JCExpression>of(makeReifiedTypeArgument(elementType), allowNull)), "inverted"), List.<JCExpression>nil()), "wrap"), List.<JCExpression>of(expr));
} else if (type.getDeclaration().equals(typeFact().getSetDeclaration())) {
Type elementType = type.getTypeArgumentList().get(0);
return make().Apply(null, makeSelect(make().Apply(null, makeSelect(make().Apply(List.<JCExpression>of(isJavaBoxableType(elementType, true) ? javaBoxType(elementType) : makeJavaType(elementType, JT_TYPE_ARGUMENT), makeJavaType(elementType, JT_TYPE_ARGUMENT)), makeQuotedFQIdent("org.eclipse.ceylon.compiler.java.wrapping.Wrappings.toCeylonSet"), List.<JCExpression>of(makeReifiedTypeArgument(elementType), allowNull)), "inverted"), List.<JCExpression>nil()), "wrap"), List.<JCExpression>of(expr));
} else if (type.getDeclaration().equals(typeFact().getMapDeclaration())) {
Type keyType = type.getTypeArgumentList().get(0);
Type itemType = type.getTypeArgumentList().get(1);
return make().Apply(null, makeSelect(make().Apply(null, makeSelect(make().Apply(List.<JCExpression>of(isJavaBoxableType(keyType, true) ? javaBoxType(keyType) : makeJavaType(keyType, JT_TYPE_ARGUMENT), isJavaBoxableType(itemType, true) ? javaBoxType(itemType) : makeJavaType(itemType, JT_TYPE_ARGUMENT), makeJavaType(keyType, JT_TYPE_ARGUMENT), makeJavaType(itemType, JT_TYPE_ARGUMENT)), makeQuotedFQIdent("org.eclipse.ceylon.compiler.java.wrapping.Wrappings.toCeylonMap"), List.<JCExpression>of(makeReifiedTypeArgument(keyType), makeReifiedTypeArgument(itemType), allowNull)), "inverted"), List.<JCExpression>nil()), "wrap"), List.<JCExpression>of(expr));
} else {
return make().Apply(null, makeSelect(javaBoxType(type), "valueOf"), List.<JCExpression>of(expr));
}
}
use of org.eclipse.ceylon.model.typechecker.model.Type in project ceylon by eclipse.
the class AbstractTransformer method makeTypeArgs.
private ListBuffer<JCExpression> makeTypeArgs(boolean isCeylonCallable, int flags, Map<TypeParameter, Type> tas, java.util.List<TypeParameter> tps, Type simpleType) {
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
for (TypeParameter tp : tps) {
Type ta = tas.get(tp);
// error handling
if (ta == null)
continue;
boolean isDependedOn = hasDependentTypeParameters(tps, tp);
// record whether we were initially working with Anything, because getNonNullType turns it into Object
// and we need to treat "in Anything" specially below
boolean isAnything = isAnything(ta);
// we want, so we make sure it's not Null
if (isOptional(ta) && !isNull(ta)) {
// For an optional type T?:
// - The Ceylon type Foo<T?> results in the Java type Foo<T>.
ta = getNonNullType(ta);
}
// In a type argument Foo<X&Object> or Foo<X?> transform to just Foo<X>
ta = simplifyType(ta);
if (typeFact().isUnion(ta) || typeFact().isIntersection(ta)) {
// conform with where raw types would be used between expressions and constructors
if (((flags & (JT_EXTENDS | JT_SATISFIES)) != 0 && tp.getSelfTypedDeclaration() != null)) {
// A bit ugly, but we need to escape from the loop and create a raw type, no generics
if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
typeArgs = null;
break;
} else if ((flags & (__JT_FULL_TYPE | JT_EXTENDS | JT_SATISFIES)) == 0) {
if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
typeArgs = null;
break;
}
// otherwise just go on
}
if (isCeylonBoolean(ta) && !isTypeParameter(ta)) {
ta = typeFact.getBooleanType();
}
JCExpression jta;
if (!tp.getSatisfiedTypes().isEmpty()) {
boolean needsCastForBounds = false;
for (Type bound : tp.getSatisfiedTypes()) {
bound = bound.substitute(tas, null);
needsCastForBounds |= expressionGen().needsCast(ta, bound, false, false, false);
}
if (needsCastForBounds) {
// replace with the first bound
ta = tp.getSatisfiedTypes().get(0).substitute(tas, null);
if (tp.getSatisfiedTypes().size() > 1 || isBoundsSelfDependant(tp) || isBoundsRecursive(simpleType, tp) || willEraseToObject(ta) || // we should reject it for all non-covariant types, unless we're in satisfies/extends
((flags & (JT_SATISFIES | JT_EXTENDS)) == 0 && !simpleType.isCovariant(tp))) {
if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
// A bit ugly, but we need to escape from the loop and create a raw type, no generics
typeArgs = null;
break;
}
}
}
if (ta.isExactlyNothing() || // use the same erasure rules as bottom: prefer wildcards
((flags & (__JT_FULL_TYPE | JT_EXTENDS | JT_SATISFIES)) != 0 && (typeFact().isUnion(ta) || typeFact().isIntersection(ta)))) {
// For the bottom type Bottom:
if ((flags & (JT_CLASS_NEW)) != 0) {
// A bit ugly, but we need to escape from the loop and create a raw type, no generics
if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
typeArgs = null;
break;
} else {
// Foo<Object> (see https://github.com/ceylon/ceylon-compiler/issues/633 for why)
if ((flags & (JT_SATISFIES | JT_EXTENDS)) != 0) {
if (ta.isExactlyNothing()) {
jta = make().Type(syms().objectType);
} else {
if (!tp.getSatisfiedTypes().isEmpty()) {
// union or intersection: Use the common upper bound of the types
jta = makeJavaType(tp.getSatisfiedTypes().get(0), JT_TYPE_ARGUMENT);
} else {
jta = make().Type(syms().objectType);
}
}
} else if (ta.isExactlyNothing()) {
// see https://github.com/ceylon/ceylon-compiler/issues/1003
if (simpleType.isContravariant(tp)) {
typeArgs = null;
break;
} else if (tp.isCovariant() && !isDependedOn) {
// DO NOT trust use-site covariance for Nothing, because we consider "out Nothing" to be the same
// as "Nothing". Only look at declaration-site covariance
jta = make().Wildcard(make().TypeBoundKind(BoundKind.EXTENDS), make().Type(syms().objectType));
} else {
jta = make().Type(syms().objectType);
}
} else {
// see https://github.com/ceylon/ceylon/issues/6365
if (((flags & JT_CLASS_NEW) == 0) && simpleType.isContravariant(tp)) /* && !isDependedOn*/
{
jta = make().Wildcard(make().TypeBoundKind(BoundKind.SUPER), makeJavaType(ta, JT_TYPE_ARGUMENT));
} else if (((flags & JT_CLASS_NEW) == 0) && simpleType.isCovariant(tp) && !isDependedOn) {
jta = make().Wildcard(make().TypeBoundKind(BoundKind.EXTENDS), makeJavaType(ta, JT_TYPE_ARGUMENT));
} else {
jta = makeJavaType(ta, JT_TYPE_ARGUMENT);
}
}
}
} else {
// For an ordinary class or interface type T:
if ((flags & (JT_SATISFIES | JT_EXTENDS)) != 0) {
// - The Ceylon type Foo<T> appearing in an extends or satisfies clause
// results in the Java type Foo<T>
jta = makeJavaType(ta, JT_TYPE_ARGUMENT);
} else {
// - Foo<? super T> if Foo is contravariant in T
if (((flags & JT_CLASS_NEW) == 0) && simpleType.isContravariant(tp) && (!isAnything || tp.isContravariant())) // FIXME: it may be necessary to uncomment this in the future,
// see https://github.com/ceylon/ceylon/issues/6365
/*&& !isDependedOn*/
{
// DO NOT trust use-site contravariance for Anything, because we consider "in Anything" to be the same
// as "Anything". Only look at declaration-site contravariance
jta = make().Wildcard(make().TypeBoundKind(BoundKind.SUPER), makeJavaType(ta, JT_TYPE_ARGUMENT));
} else if (((flags & JT_CLASS_NEW) == 0) && simpleType.isCovariant(tp) && !isDependedOn) {
jta = make().Wildcard(make().TypeBoundKind(BoundKind.EXTENDS), makeJavaType(ta, JT_TYPE_ARGUMENT));
} else {
jta = makeJavaType(ta, JT_TYPE_ARGUMENT);
}
}
}
typeArgs.add(jta);
if (isCeylonCallable) {
// In the runtime Callable only has a single type param
break;
}
}
return typeArgs;
}
use of org.eclipse.ceylon.model.typechecker.model.Type in project ceylon by eclipse.
the class AbstractTransformer method getFirstRefinedDeclaration.
private TypedDeclaration getFirstRefinedDeclaration(TypedDeclaration decl) {
if (decl.getContainer() instanceof ClassOrInterface == false)
return decl;
java.util.List<Type> signature = org.eclipse.ceylon.model.typechecker.model.ModelUtil.getSignature(decl);
boolean variadic = org.eclipse.ceylon.model.typechecker.model.ModelUtil.isVariadic(decl);
boolean overloaded = decl.isOverloaded() || decl.isAbstraction();
Declaration refinedDeclaration = decl.getRefinedDeclaration();
if (refinedDeclaration != null) {
overloaded |= refinedDeclaration.isOverloaded() || refinedDeclaration.isAbstraction();
}
ClassOrInterface container = (ClassOrInterface) decl.getContainer();
HashSet<TypeDeclaration> visited = new HashSet<TypeDeclaration>();
// start looking for it, but skip this type, only lookup upwards of it
TypedDeclaration firstRefinedDeclaration = getFirstRefinedDeclaration(container, decl, signature, variadic, visited, true, overloaded);
// only keep the first refined decl if its type can be trusted: if it is not itself widening
if (firstRefinedDeclaration != null) {
if (CodegenUtil.hasUntrustedType(firstRefinedDeclaration))
firstRefinedDeclaration = getFirstRefinedDeclaration(firstRefinedDeclaration);
}
return firstRefinedDeclaration != null ? firstRefinedDeclaration : decl;
}
Aggregations