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

Optional field in a class satisfying I<Nothing> #2051

Open
jpragey opened this issue Feb 6, 2015 · 5 comments
Open

Optional field in a class satisfying I<Nothing> #2051

jpragey opened this issue Feb 6, 2015 · 5 comments
Assignees
Milestone

Comments

@jpragey
Copy link

jpragey commented Feb 6, 2015

Compiling:

shared interface II{}

shared interface I<T> 
        given T satisfies II 
{
    shared default T? field => null;
}

shared class A() satisfies I<Nothing>{}

shared void run() {
    object a1 extends A(){} // Issue here
}

prints:

error: A is not abstract and does not override abstract method getField() in I
source/org/bug/run.ceylon:13: error: getField() in A cannot implement getField() in I
    object a1 extends A(){} // 
              ^
  return type Object is not compatible with II
  where T is a type-variable:
    T extends II declared in interface I
2 errors
1 warning
@tombentley tombentley modified the milestone: 1.2 Feb 9, 2015
@gavinking gavinking added the BUG label Feb 20, 2015
@tombentley tombentley self-assigned this Feb 26, 2015
@tombentley
Copy link
Member

This one is difficult and seems to members with T or T? where T has a non-erased upper bound. Thus it affects setter, methods and method parameters (and I guess the parameter types of instantiator methods too). The typechecker decides the produced type of field in A must be Null, and so we generate j.l.Object, losing sight of the fact that the result is a constrained type parameter, (and therefore that Object is a wider type).

The problem is that figuring out what the correct type should be isn't at all easy, because the constraint on the type parameter T can be on a subtype of the type which declared the member (field).

interface Top<T> {
    shared default T field;
}
interface Constrained<T> satisfies Top<T> given T satisfies II {}
class C() satisfies Constrained<II> {}

Knowing what the constraints on T are, I can then use the type I<II> instead of I<Nothing> to obtain the typed member. But I'm not really sure that's the right thing to be doing here: It feels like I would end up reproducing a lot of the logic of the typechecker.

Any ideas @FroMage, @gavinking?

@FroMage
Copy link
Member

FroMage commented Feb 27, 2015

I thought we had logic in nonWideningType that dealt with something that erases to Object overriding something that was T? Perhaps it's just missing the case for T??

@tombentley
Copy link
Member

No, it's really not as simple as that. The algorithm seems to go wrong, I think because within the Ceylon model Nothing satisfies T, so we don't realize there's (going to be) widening once Nothing is erased to Object.

@FroMage
Copy link
Member

FroMage commented Feb 27, 2015

Damn. Well, then I'm out of idea. Going up to find the contraints on our side seems error-prone, but it's not like I have a better idea.

@FroMage
Copy link
Member

FroMage commented Apr 10, 2015

Let's move it to 1.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants