Hi -
> Of course if we want to define intuitive as "do it like Java", we make
> def an alias for var, take its semantics and give up on Flow typing in
> general.
Nobody wants to give up flow typing.
> If we do not give up on flow typing, then I would like to
> know why the assignment should not be legal. And if it is legal in the
> if-branch, then why not in the Closure block?
All assignments should be legal, and assignment in Closure block as well.
Let me annotate the last example with types:
class A {}
class B extends A{ def b() {}}
class C extends A{}
A x // inferred to A because LUB(B,C) = A
x = new B()
// typeOf(x) as this point is B due to flow typing
if (true) {
x = new C()
// typeOf(x) as this point is C due to flow typing
}
// typeOf(x) as this point is A due to flow typing merging branches where
typeOf(x) is B and C
A z // inferred to A because LUB(A) = A
z = x
// typeOf(z) as this point is A
z.b() // STC error, no method b in A
—
Daniil Ovchinnikov
JetBrains
> On 4 Jun 2020, at 21:47, Jochen Theodorou <[email protected]> wrote:
>
> On 04.06.20 18:55, Milles, Eric (TR Tech, Content & Ops) wrote:
>> I am suggesting that when a closure is encountered, it is treated like an
>> optional branch of the code. So assignments within alter the inferred type
>> the same way an assignment within an if with no else would.
>
> sure I am for that, but I am not sure we are doing those right either ;)
>
>> I am not looking to examine the code flow and distinguish between closure
>> executed immediately and closure that is executed asynchronously or later or
>> not at all.
>
> me neither
>
> [...]
>> If you are talking about using a union type,
>
> did not want to really use that word, because I think people understand
> different things about it, but basically yes. Let me call it Least Upper
> Bounds Union Type (LUBU)
>
>> I don't think that is the safe way to go. Static compilation is enforcing a
>> typecast to the inferred type and this is a runtime error for 9344.
>
> If you say that then
>
>> class A{}
>> class B{}
>>
>> def a = new A()
>> a = new B()
>
> must fail, because the inferred type for a is A, so I cannot assign B to
> it. That is quite far away from the initial idea. Of course you are more
> referring to
>
>> class A{}
>> class B{}
>> class C{}
>>
>> def a = new A()
>> if (b) {
>> a = new B()
>> }
>> a = new C()
>
> but again, each of these assignments are legal in my opinion. The real
> question should be if in
>
>> class A {}
>> class B extends A{ def b() {}}
>> class C extends A{}
>>
>> def x = new B()
>> if (true) { x = new C() }
>> def z = x
>> z.b()
>
> The call z.b() is legal. And my answer is here with LUBU yes, with LUB,
> as we have defined it probably no. But I find the later not intuitive.
>
> Of course if we want to define intuitive as "do it like Java", we make
> def an alias for var, take its semantics and give up on Flow typing in
> general. Then my two examples here should both fail compilation on the
> reassignment. If we do not give up on flow typing, then I would like to
> know why the assignment should not be legal. And if it is legal in the
> if-branch, then why not in the Closure block?
>
>
> bye Jochen