Description
Compiler version
Minimized code
object O:
opaque type T = Int
inline def x: Int = P.id(2)
object P:
def id(x: O.T): O.T = x
object Test {
def main(args: Array[String]): Unit = println(foo())
def foo(): Int = O.x
}
Output
-- [E007] Type Mismatch Error: tests/run/hello.scala:11:21 ---------------------
11 | def foo(): Int = O.x
| ^^^
| Found: (2 : Int)
| Required: O.T
|----------------------------------------------------------------------------
|Inline stack trace
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|This location contains code that was inlined from hello.scala:3
3 | inline def x: Int = P.id(2)
| ^
----------------------------------------------------------------------------
|
| longer explanation available when compiling with `-explain`
1 error found
Note that error happens during inlining. The code originally typechecks.
Expectation
Either there should be a compile error at the definition of O.x
, or inlining O.x
should succeed.
Analysis
The definition of O.x
can be seen as a bit dubious, since it needs Int =:= O.T
. Normally, the alias of an opaque type alias is only visible when accessed through a this
prefix (Int =:= this.T
is true). The documentation for opaque type aliases has a specific rule for this case: within the definition of O
, we accept that O.T
can see the alias. This is supposed to be fine, since we know that O eq this
. I am not sure how the compiler even allows that in the first place, though.
Once inlined, however, the O.T
escapes the scope of O
. And that causes an issue. Normally, opaque aliases are seen after inlining because (IIUC what @odersky told me) the val $this
receives a more specific type which contains the aliases of opaque types in a refinement. That's fine for this.T
references, which become $this.T
, but it does not help for those out-of-band references O.T
. Once outside the definition of O
, they break.
TBH I don't see how inlining can fix this in the general case. Simple cases might be patched up with some casts, but it doesn't work for general subtyping relationships.
This makes me question the validity of the special rule in the first place. 😕