Open jvasileff opened 7 years ago
The problem with looking up members in the union type is that the metamodel has to work on JS, and on JS we don't have the typechecker to rely on for forming principle instantiations, as mentioned here in #5384. So I'm not sure this one is simply a matter of diving in an hacking the metamodel into compliance.
For JS, 1) I didn't test it fully, but in at least a few cases it seemed to work well, and 2) longer term it might be possible for @chochos to integrate the model I've written in Ceylon into the JS backend.
I guess you're suggesting we might want to find some other approach that requires less of the model, but I'm not sure what that would be without losing capabilities (i.e. returning null
too often, returning less refined declarations, or something else)
A couple additional comments:
class A1<T>(T t) {
shared class B() {
shared T t => outer.t;
}
}
class A2() extends A1<Integer>(1) {}
value ab = `class A1.B`.memberClassApply<A2,A2.B,[]>(`A2`)(A2());
where we need the A1
supertype of A2
. Much more complex examples could be crafted.
Type
might work out very well, and would eliminate the need for Container
. This is practical since we now have use-site variance. I have the very beginnings of an API for this that wraps the current meta-model, which so far seems encouraging.
In ClassOrInterface.getClassOrInterface() and similar methods, results not belonging to the receiver may be returned.
Background
Due to
Type<>
being covariant in its type parameter, the variousgetMember()
methods have their ownContainer
type parameters so that the receiver type can be represented in a contravariant type parameter in the return. This allows for typesafe application of the returned value.For example, a
Type<>
with the static typeType<Anything>
may represent aString
, but a member ofString
must be bound to aString
, and not just some otherAnything
. So,Anything
would not be a suitable type to use for the return value'sContainer
.The type parameter
Container
is intended to act as a filter per the documentation linked above, and as discussed in #5384.Current Implementation
By example, for
x.getAttribute<Container>("member")
, the current implementation:x
has a member named "member" and returnsnull
if notContainer
has a member named "member" and returnsnull
if notBut (3) offers no guarantees about the member's applicability to
x
. This is not consistent with the documented rules, and can produce surprising results.I believe the correct algorithm would be to search for the member in the union type
x | Container
as suggested in this comment https://github.com/ceylon/ceylon/issues/5384#issuecomment-156671507.Test Cases