eclipse-archived/ceylon

unsound refinement with inferred return type

gavinking opened this issue · 2 comments

The typechecker should not accept this unsound code:

Iterable<Iterable<Element?,Absent2>,Absent1> transpose<Element,Absent1,Absent2>
        (Iterable<Iterable<Element,Absent1>,Absent2> streams)
        given Absent1 satisfies Null
        given Absent2 satisfies Null
        => object satisfies Iterable<Iterable<Element?,Absent2>,Absent1> {
    value iterators = streams.collect((stream) => stream.iterator());
    iterator() => object satisfies Iterator<Iterable<Element?,Absent2>> {
        shared actual function next() {
            value elements = iterators.collect((it) => it.next());
            return elements.every((it) => it is Finished) then finished 
            else elements.collect((it) => if (is Finished it) then null else it);
        }
    };
};

OK, so this is a problem with typechecking return in refined members with inferred type.

//OK
class X() {
    shared actual function equals(Object x) => 1; //error
    shared actual value string => 1; //error
}

//OK
class Y() {
    equals(Object x) => 1; //error
    string => 1; //error
}

//BAD
class Z() {
    shared actual function equals(Object x) {
        return 1; //NO ERROR!
    }
    shared actual value string {
        return 1; //NO ERROR!
    }
}

Ugh, that's really nasty. At least this is an undocumented feature. :-/

Heh. So this bug exists in all released versions of Ceylon 1.3, and nobody ever noticed.