eclipse-archived/ceylon

JVM / JS behavior mismatch for `Range<Element>` satisfying `{Element+}`at runtime

Closed this issue · 3 comments

The following code:

shared void run() {
	value manual = {{1,2,3,4,5,6,7,8,9,10}}; 
	value firstMan = manual.first;
	if (is {Integer+} firstMan) {print ("ok");} else { print("Ups.."); } // Ok
	if (is {{Integer+}+} manual) { print("ok"); } else { print("Ups.."); } // Ok
	
	value range = { 1:10 };
	value firstRan = range.first;
	if (is {Integer+} firstRan) {print ("ok");} else { print("Ups.."); } // Ok
	if (is {{Integer+}+} range) { print("ok"); } else { print("Ups.."); } // Ups...
}

Prints three Ok and one Ups.. in JVM, but four Okin JS (Web Ide).

Seems related to the fact 1:10 is not just a {Integer+}, but a []|{Integer+}.

This is a bug in the JS compiler. Here is a simple program that demonstrates unsoundness:

shared void run() {
    assert (is {{Integer+}+} emptyRangeStream = { 1:-10 });  //should fail here, but doesn't
    Integer i = emptyRangeStream.first.first;
    print(i.string);  //blows up here
}

This program should cause an assertion failure. But instead it blows up at the print() statement.

Something in the is function, apparently:

    Object foo = {1:-10};
    if (is {{Integer+}+} foo) { //shouldn't happen but we go in
        Object bar = foo.first;
        print(bar); //[]
        print(className(bar)); //c.l::empty
        print(bar is {Integer+}); //FALSE
    }

Actually this even fails with foo = {[]}

Thanks @chochos!