eclipse-archived / ceylon

The Ceylon compiler, language module, and command line tools
http://ceylon-lang.org
Apache License 2.0
395 stars 62 forks source link

Inconsistent handling of intersections w/type parameter & upper bound constraints #7383

Closed jvasileff closed 5 years ago

jvasileff commented 5 years ago

The intersection of a type parameter and its upper bound constraints simplifies to just the type parameter. For example, the intersection of T satisfies Object and Object (T & Object) is "just" T.

However, "redundant" intersection components are meaningful when substituting a type that is not a subtype of T's upper bound constraints into T. For example, after substituting an unconstrained U into T for use in the expression T & Object, the result will be U & Object, not "just" U as it would be for the simplified expression T.

The "simplification" of types like T & Object is unintentionally material, and inconsistently performing type simplifications can produce inconsistent results.

An example of this on the JVM backend is when a type like T & Object is used as the type of a shared member. It is not simplified for code that is compiled at the same time, but it is simplified in the stored model used for future compiles.

The attached two-module project demonstrates this. Compiling the modules at the same time works:

$ ceylon compile
Note: Created module app/1.0.0
Note: Created module lib/1.0.0

but compiling separately fails:

$ ceylon compile lib ; ceylon compile app
Note: Created module lib/1.0.0
source/app/run.ceylon:4: error: specified type does not cover the cases of the operand expression: 'Object' does not cover 'T'
    noop(c.t of Object);
         ^
1 error
Note: Created module app/1.0.0
ceylon compile: There was 1 error

The relevant code in module lib is:

shared class C<T>(shared T & Object t) given T satisfies Object {}

and in app:

import lib { C }

void f<T>(C<T> c) {
    noop(c.t of Object);
}
jvasileff commented 5 years ago

The sample project - bug7383.zip

RossTate commented 5 years ago

This is one reason why Java infers implicit constraints for wildcards. Not saying y'all should do that - it's just interesting to see an example in practice.

gavinking commented 5 years ago

So I don't know why the Java backend canonicalizes types in TypeInfo annotations, and I think it's wrong that it does. The offending line of code is AbstractTransformer:3746.

gavinking commented 5 years ago

@jvasileff could you check that be37326 fixes the problem please?

jvasileff commented 5 years ago

I don't have anything except the sample project, so if ceylon compile lib && ceylon compile app works I guess were good.

gavinking commented 5 years ago

OK, @jvasileff, great, closing.