ceylon
ceylon copied to clipboard
problem implementing higher-order generics
I'm trying to add support to the JVM backend for the following code:
import ceylon.language.meta.model {
Attribute
}
shared interface Model<Parent,Result> given Result<T> {
shared formal Result<Type> get<Type>(Attribute<Parent,Type> attribute);
}
shared interface Expression<T> satisfies Model<T,Expression> {
shared actual Expression<Type> get<Type>(Attribute<T,Type> attribute)
=> object satisfies Expression<Type> {};
}
Here's what I currently have:
diff --git a/compiler-java/src/com/redhat/ceylon/compiler/java/codegen/AbstractTransformer.java b/compiler-java/src/com/redhat/ceylon/compiler/java/codegen/AbstractTransformer.java
index b08e447526..40a3bb2189 100755
--- a/compiler-java/src/com/redhat/ceylon/compiler/java/codegen/AbstractTransformer.java
+++ b/compiler-java/src/com/redhat/ceylon/compiler/java/codegen/AbstractTransformer.java
@@ -1571,9 +1571,14 @@ public abstract class AbstractTransformer implements Transformation {
}
private boolean isTurnedToRawResolved(Type type) {
+ if (type.isTypeConstructor())
+ return true;
// if we don't have type arguments we can't be raw
if(type.getTypeArguments().isEmpty())
return false;
+
+ if (type.isTypeParameter())
+ return true;
// we only go raw if any type param is an erased union/intersection
// start with type but consider ever qualifying type
@@ -1585,6 +1590,8 @@ public abstract class AbstractTransformer implements Transformation {
Map<TypeParameter, Type> typeArguments = singleType.getTypeArguments();
for(TypeParameter tp : declaration.getTypeParameters()){
Type ta = typeArguments.get(tp);
+ if (ta.isTypeConstructor())
+ return true;
// skip invalid input
if(tp == null || ta == null)
return false;
@@ -1927,6 +1934,11 @@ public abstract class AbstractTransformer implements Transformation {
if(type == null || type.isUnknown())
return make().Erroneous();
+ if (type.isTypeConstructor() ||
+ type.isTypeParameter() && !type.getTypeArgumentList().isEmpty()) {
+ type = type.getDeclaration().getUnit().getObjectType();
+ }
+
if (type.getDeclaration() instanceof Constructor) {
type = type.getExtendedType();
}
@@ -2480,6 +2492,11 @@ public abstract class AbstractTransformer implements Transformation {
// and we need to treat "in Anything" specially below
boolean isAnything = isAnything(ta);
+ if (ta.isTypeConstructor()) {
+ typeArgs = null;
+ break;
+ }
+
// Null will claim to be optional, but if we get its non-null type we will land with Nothing, which is not what
// we want, so we make sure it's not Null
if (isOptional(ta) && !isNull(ta)) {
diff --git a/compiler-java/src/com/redhat/ceylon/compiler/java/codegen/Strategy.java b/compiler-java/src/com/redhat/ceylon/compiler/java/codegen/Strategy.java
index e8ff5170cc..1121056cb3 100644
--- a/compiler-java/src/com/redhat/ceylon/compiler/java/codegen/Strategy.java
+++ b/compiler-java/src/com/redhat/ceylon/compiler/java/codegen/Strategy.java
@@ -555,6 +555,9 @@ class Strategy {
}
} else if (decl instanceof TypeAlias) {
return ((TypeAlias)decl).getTypeParameters();
+ }
+ else if (decl instanceof TypeParameter) {
+ return Collections.emptyList();
} else {
throw BugException.unhandledDeclarationCase((Declaration)decl);
}
diff --git a/typechecker/src/com/redhat/ceylon/compiler/typechecker/analyzer/ExpressionVisitor.java b/typechecker/src/com/redhat/ceylon/compiler/typechecker/analyzer/ExpressionVisitor.java
index 55da0271ad..7ddd06f70e 100644
--- a/typechecker/src/com/redhat/ceylon/compiler/typechecker/analyzer/ExpressionVisitor.java
+++ b/typechecker/src/com/redhat/ceylon/compiler/typechecker/analyzer/ExpressionVisitor.java
@@ -8138,10 +8138,10 @@ public class ExpressionVisitor extends Visitor {
}
if (pt.isTypeConstructor()
&& !that.getMetamodel()) {
- checkNotJvm(that,
- "type functions are not supported on the JVM: '" +
- type.getName(unit) +
- "' is generic (specify explicit type arguments)");
+// checkNotJvm(that,
+// "type functions are not supported on the JVM: '" +
+// type.getName(unit) +
+// "' is generic (specify explicit type arguments)");
}
}
}
@@ -9982,8 +9982,8 @@ public class ExpressionVisitor extends Visitor {
TypeParameterList typeParams =
that.getTypeParameterList();
if (typeParams!=null) {
- checkNotJvm(typeParams,
- "type functions are not supported on the JVM: type parameter is generic (remove type parameters)");
+// checkNotJvm(typeParams,
+// "type functions are not supported on the JVM: type parameter is generic (remove type parameters)");
}
}
I'm currently stuck on the fact that the compiler, instead of throwing any sort of error, simply ignores the Expression interface.
Over to you @FroMage ;-)
So this stops generation of the second interface because it contains unknown types. This is done in DeclarationErrorVisitor#177. You can debug the generation in IssuesTests_7000_7499.testBug7000 on the 7000 branch.
OK great thanks
Relates to #2358.