Closed
Description
Compiler version
3.2.2 , 3.3.0-RC3
Minimized code
class A
class B extends A:
def m = true
//transparent inline def choose(b: Boolean): A =
// if b then new A else new B
def choose(b:Boolean):B = new B
class X:
val obj1 : A
val obj2 : A
val obj3 : A
class Y extends X:
val obj0 = choose(false) // type B ( from inference )
val obj1 = choose(false) // type A ( from X.this.obj1 )
val obj2 : B = choose(false) // type B ( from ascription )
final val obj3 = choose(false) // type B ( from inference )
val y = new Y
y.obj0.m // compiles EXPECTED
y.obj1.m // compile error UNEXPECTED
y.obj2.m // compiles EXPECTED
y.obj3.m // compiles EXPECTED // Why different from obj1 case ?
Output
y.obj1.m ---- m is not a member of A
Expectation
The issue is the type of the val objN
in Y
.
obj0
: EXPECTED. Type isB
as inferred fromchoose( )
return type.obj1
: UNEXPECTED. Type isA
, widened to the abstract definitionval obj1:A
inX
obj2
: EXPECTED. Type isB
, from the type-ascription.obj3
: ???. Type isB
. Thefinal
modifier has an impact on the member type (vs.obj1
), and seems to restore expected type inference. On the other hand making the entireclass Y
final has no impact.
Observations
You may notice a pattern very close to the one described here. The bug is not caused bug transparent inline
, but loses the on-purpose crafted type.
In scala2 the type was the expected one. scastie
class A { }
class B extends A { def m = true }
trait X { def obj : A }
class Y extends X { def obj = new B }
val y = new Y
y.obj.m // Compiles in scala2, does not compile in scala3.
- Is the change of behavior between scala2 and scala3 intentional ?
- Is the impact of
final
on the type of the member expected ?