JVM compiler really doesn't react well to higher order generics
lukedegruchy opened this issue · 0 comments
lukedegruchy commented
The JVM compiler outputs some rather cryptic compile errors in an IDE project where higher order generics were successfully compiled as JavaScript only.
This issue requests the implementation of clearer compile errors along the lines of "JVM compiler does not currently support Higher Order Generics feature" as opposed to the compile errors below.
Please see #2358 for the actual implementation of the feature on the JVM.
Apologies for the lengthly sample, but I figured this is good to capture the broad range of possible compile errors. Please note that this occurred on a production 1.2.0 Eclipse IDE, not one recently built from github sources.
Look for "JVM compile errors comments in the code below:
import ceylon.collection {
LinkedList
}
shared void genericFunctionDefinitions() {
alias ValueToValueValue => <Value> => [Value,Value];
alias Pair<Value> => [Value,Value];
// JVM compile error:
// package SecondOrder does not exist
interface SecondOrder<Box> given Box<Value> {
shared formal Box<Float> createBox(Float float);
}
//apply to a generic type alias
SecondOrder<Pair> something;
//apply to a generic interface
// List *is* a Type Function even though it already exists as something else
SecondOrder<List> somethingElse;
//apply to an anonymous type function
SecondOrder<<Value> => [Value,Value]> somethingScaryLookin;
Any pipe<Any>(Any anything) => anything;
Number add<Number>(Number x, Number y)
given Number satisfies Summable<Number>
=> x+y;
// Are these both the same thing?
alias AnyAnyAny => <Any> => Any(Any);
alias AnyAny<Any> => Any(Any);
alias AdditionLikeOperation
=> <Number> given Number satisfies Summable<Number>
=> Number(Number,Number);
alias AdditionLikeOperationSimple<Number>
given Number satisfies Summable<Number>
=> Number(Number,Number);
}
void genericFunctionReferences() {
// generic function definition
Any pipe<Any>(Any anything) => anything;
// generic function reference
<Any> => Any(Any) pipeFun = pipe;
// generic function definition
Number add<Number>(Number x, Number y)
given Number satisfies Summable<Number>
=> x+y;
// generic function alias
alias AdditionLikeOperation
=> <Number> given Number satisfies Summable<Number>
=> Number(Number,Number);
// generic function reference with raw function type
<Number> given Number
satisfies Summable<Number>
=> Number(Number,Number) addFun = add;
// generic function reference with alias
AdditionLikeOperation addFunWithAlias = add;
// Simply pass the type to the generic function to create a function with the types set
String(String) pipeString = pipeFun<String>;
Object(Object) pipeObject = pipeFun<Object>;
// Call the functions using type inference to obtain the resulting value
String hi = pipeFun("hello");
Integer zero = pipeFun(0);
// generic function general form:
// <TypeParameters> => ReturnType(ParameterTypes)
// Take a Stream of elements and produce another Stream of elements
// Define the Stream of elements returned in terms on the type constructor of the
// Stream<Elem> param
Stream<Elem> scan<Elem,Stream>
(inputStream, newStream)
//Note: Stream is a reference to a type function!
given Stream<Elem> satisfies {Elem*} {
// This is the original Stream
Stream<Elem> inputStream;
// This it the function type that will return a stream for a Stream of elements
Stream<Elem> newStream<Elem>(Stream<Elem> elements);
return nothing;
}
// Note: I need Stream as well as Elem as a type parameter or this won't compile
Stream<Elem> newStream<Stream,Elem>({Elem*} elements)
given Stream<Elem> satisfies {Elem*};
// 1) Iterable case:
{Integer*} iterableInput = {1,2,3};
scan<Integer,Iterable>(iterableInput, <Elem>({Elem*} elems) => elems);
// 2) LinkedList case:
LinkedList<Integer> linkedListInput = LinkedList{1,2,3};
// JVM compile errors:
// compiler bug: unhandled declaration unknown with type UnknownType at com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.makeReifiedTypeArgumentResolved(AbstractTransformer.java:5245)
// compiler bug: visitor didn't yield any result at com.redhat.ceylon.compiler.java.codegen.ExpressionTransformer.transformExpression(ExpressionTransformer.java:340)
// compiler bug: visitor didn't yield any result at unknown
scan<Integer,LinkedList>(linkedListInput, LinkedList);
Stream<Elem> newScan<Elem,Stream>
(inputStream, newStream)
//Note: Stream is a reference to a type function!
given Stream<Elem> satisfies {Elem*} {
// This is the original Stream
Stream<Elem> inputStream;
// This it the function type that will return a stream for a Stream of elements
Stream<Elem> newStream<Elem>({Elem*} elements);
return nothing;
}
// 1) Iterable case:
{String*} iterableInput2 = {"1","2","3"};
newScan<String,Iterable>(iterableInput2, <Elem>({Elem*} elems) => elems);
// 2) LinkedList case:
LinkedList<String> linkedListInput2 = LinkedList{"1","2","3"};
// JVM compile errors:
// compiler bug: unhandled declaration unknown with type UnknownType at com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.makeReifiedTypeArgumentResolved(AbstractTransformer.java:5245)
// compiler bug: visitor didn't yield any result at com.redhat.ceylon.compiler.java.codegen.ExpressionTransformer.transformExpression(ExpressionTransformer.java:340)
// compiler bug: visitor didn't yield any result at unknown
newScan<String,LinkedList>(linkedListInput2, LinkedList);
}