According to the Section 11.7.5 of the OCL Specification 2.4 Sequence type has the following operation:

including(object : T) : Sequence(T)

I expect that the following expression will return invalid value.

Sequence{1, 2, 3}->including('string')

Because operation including(String) is not defined for Sequence(Integer). I expect that type T of the argument must conform to the type T of the source Sequence(T). Also the resulting and source collections will have the same Sequence(T) type.

But the result of the expression is the Sequence{1,2,3,'string'} with a Sequence(OclAny) type.

Even the following expression has the same result:

let coll : Sequence(Integer) = Sequence{1,2,3} in coll->including('string')

Is it true that OCL Sequence(T) is covariant on T? Integer is a subtype of OclAny. So Sequence(Integer) is a subtype of Sequence(OclAny). And so the operation including(OclAny) is defined for Sequence(Integer)?]]>

It is intuitive to get confused with Java libraries where collections are mutable so the resulting collection obviously has the same type as the source collection. However in OCL, Collections are immutable and so the result is a brand new collection which can have a brand new type. It is therefore a language design decision whether the declaration of "Sequence(T)::including(T) : Sequence(T)" is allowed full freedom to find a T that satisfies the usage, or whether T must be precisely bound to the actual source collection. Full freedom seems more declarative and sensible and so that is how Eclipse OCL has evolved in its prototype of this ambiguity. In practice Sequence(Integer) evolving into a Sequence(OclAny) is 'correct' but surprising. However it should not be dangerous since downstream something should complain that your Sequence(Integer) has got polluted.

Regards

Ed Willink]]>

Here is a related example:

let realCollection : Sequence(Real) = Sequence{1.0, 2,0, 3,0} in let intCollection : Sequence(Integer) = realCollection in intCollection->including(1)

let intCollection : Sequence(Integer) = Sequence{1, 2, 3} in let realCollection : Sequence(Real) = intCollection in realCollection->including(1)

The first expression has a Sequence(Integer) type. And the second one - Sequence(Real). I think that the first expression must be incorrect, because Sequence(Real) can not be casted to Sequence(Integer)...]]>

Agree and agree. Which is why substantial improvements are required to the OCL specification, but we need the models and prototype to move on from the current manual best endeavors.

The first example gives me:

The 'Variable::CompatibleInitialiserType' constraint is violated for 'intCollection : Sequence(Integer) = realCollection'

in the Interactive Xtext OCL Console.

Regards

Ed Willink]]>