ceylon icon indicating copy to clipboard operation
ceylon copied to clipboard

Ceylon backend error: method invoked with incorrect number of arguments

Open jogro opened this issue 8 years ago • 4 comments

This function:

{<Annot->ProgramElement>*} annotatedMembers<Annot, ProgramElement>(
    Class<OptionalAnnotation<Annot, ProgramElement>> annotType, 
    Package pkg)
        given Annot satisfies OptionalAnnotation<Annot, ProgramElement>
        given ProgramElement satisfies NestableDeclaration {
    variable {<Annot->ProgramElement>*} results = {};
    for (element in pkg.annotatedMembers<ProgramElement,Annot>()) {
        assert(exists annotation = optionalAnnotation(annotType, element));
        results = results.follow(annotation->element);
    }
    return results;
}

And this annotation

final sealed annotation class SomeAnnotation()
        satisfies OptionalAnnotation<SomeAnnotation,FunctionDeclaration> {
}

Generates a backend error:

shared void backendError() {
    annotatedMembers(`SomeAnnotation`, `package`); //Ceylon backend error: method invoked with incorrect number of arguments; expected 4, found 0
    annotatedMembers(`SharedAnnotation`, `package`); //Compiles
}

jogro avatar Sep 17 '17 09:09 jogro

Thanks for reporting.

gavinking avatar Sep 17 '17 09:09 gavinking

I can also reproduce this problem with VariableAnnotation.

The difference between VariableAnnotation and SharedAnnotation is that SharedAnnotation has a union-typed argument to the type parameter ProgramElement of OptionalAnnotation.

gavinking avatar Apr 27 '18 09:04 gavinking

Alright, so the issue here is rooted in the fact that ProgramElement is (correctly, it seems to me, according to the rules, given that it occurs only contravariantly in the parameter list) assigned the inferred type Nothing.

This Nothing results in some sort of very complex interaction between type constraints that I still don't fully grok, and triggers the bug. But actually Nothing wasn't a useful type argument to begin with.

Supplying an explicit type argument fixes the code from a logical point of view, and avoids the bug:

annotatedMembers<SomeAnnotation,FunctionDeclaration>(`SomeAnnotation`, `package`);

gavinking avatar Apr 27 '18 10:04 gavinking

I can also fix the code by introducing an intervening interface which redeclares ProgramElement as an invariant type parameter:

interface MyOptionalAnnotation<Annot, ProgramElement> 
        of Annot  
        satisfies OptionalAnnotation<Annot,ProgramElement> 
        given Annot satisfies MyOptionalAnnotation<Annot,ProgramElement> 
        given ProgramElement satisfies Annotated {}

{<Annot->ProgramElement>*} annotatedMembers<Annot,ProgramElement>(
    Class<MyOptionalAnnotation<Annot,ProgramElement>> annotType, 
    Package pkg)
        given Annot satisfies OptionalAnnotation<Annot, ProgramElement>
        given ProgramElement satisfies NestableDeclaration {
    variable {<Annot->ProgramElement>*} results = {};
    for (element in pkg.annotatedMembers<ProgramElement,Annot>()) {
        assert(exists annotation = optionalAnnotation(annotType, element));
        results = results.follow(annotation->element);
    }
    return results;
}

final sealed annotation class SomeAnnotation()
        satisfies MyOptionalAnnotation<SomeAnnotation,FunctionDeclaration> {
}

gavinking avatar Apr 27 '18 10:04 gavinking