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 <blackd...@gmx.org> 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

Reply via email to