Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JVM compiler really doesn't react well to higher order generics #2411

Open
lukedegruchy opened this issue Nov 1, 2015 · 0 comments
Open
Assignees
Labels
Milestone

Comments

@lukedegruchy
Copy link

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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants