Why union type for members with the same name doesn't behave similar to intersection type?

trait Foo1:
  def foo: Int

trait Foo2:
  def foo: String
    
val foo1and2: (Foo1 & Foo2) = ???
val x: Int & String = foo1and2.foo  

But for

val foo1or2: (Foo1 | Foo2) = ???
val x: Int | String = foo1or2.foo  

there is an error
value foo is not a member of Foo1 | Foo2

2 Likes

The discussion began at https://github.com/lampepfl/dotty/discussions/14174 before getting chased off their lawn.

I think it’s because of overloading, per that answer: in the intersection case, you know you have an overloaded member f, and you can choose statically between them, but in the union case, you don’t. That seems OK for nilary methods, but what if they take parameters?

Maybe it’s a use case that I want to invoke f reflectively with N args, tell me if there any viable alternative? Is that better than nothing?

We can look at Typescript. It has union and intersection types. Actually, that’s why it was a surprise for me that scala doesn’t work the same way.

https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgGIHt0EZkG8BQyyMmAXMiAK4C2ARtPgL776iSyIoboBMehxMsgDOYKKADmTFgBMICADZwoKBOhCjB2dFB7luOAD5pMPfGo1hkAD2QBeLVh08AdCXT4A9J6JEAegD8LCxs0PBIJtgw-ETu5AAU1qRUdNAAlPYAfBQ09FDSrOBhnJE80QSxQonkouIgEhl22Sl5BXKKyqrqmu5OujD6mFjRxtxl5t1W0Q69zjBumF4+voEsQA