-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
type aliases leak underlying opaque types through separate compilation #13377
Comments
It looks like the type alias is quite important, which is not emphasised in the description. Everything seems to behave as expected if we use |
OK, it looks like match types have nothing to do with this, and any type referencing (aliasing) within the opaque source code is exposed to leaks via separate compilation. Minimized codeSee minimized branch at: https://github.com/soronpo/dottybug/tree/opaque_loss main/scala/core/Foo.scala package core
opaque type Foo[T] <: Int = Int
type LeakFoo[T] = Foo[T] main/scala/LeakFoo.scala import scala.util.NotGiven
type LeakFoo[T] = core.LeakFoo[T]
val ok = summon[NotGiven[LeakFoo[1] =:= LeakFoo[2]]] test/scala/Foo.scala import scala.util.NotGiven
val notok = summon[NotGiven[LeakFoo[1] =:= LeakFoo[2]]] Output[error] 2 |val notok = summon[NotGiven[LeakFoo[1] =:= LeakFoo[2]]]
[error] | ^
[error] |no implicit argument of type util.NotGiven[core.Foo$package.Foo[(1 : Int)] =:=
[error] | core.Foo$package.Foo[(2 : Int)]
[error] |] was found for parameter x of method summon in object Predef
[error] one error found |
The problem is that the opaque type is defined toplevel in a package rather than a class or object. I have looked into it in depth now, but I have not yet found a way to make this work. There might be too many assumptions about packages that prevent us from mapping opaque type members to their bounds. So a possible outcome might be add a restriction that opaque types cannot be toplevel. |
We define IArray as a top-level opaque type so it won't be easy to walk that back. |
I just checked and indeed if I place the opaque in an object and export it to top-level or alias it into top-level the problem goes away. //at top-level
opaque type Foo = Int Will change into export `$opaqueFoo`.Foo
object `$opaqueFoo`:
opaque type Foo = Int This is an ugly hack, but maybe the easiest way to solve the problem. |
@odersky Do you know what's different in the model between the separate and the joint compilation scenarios? |
I could track it down to a difference in the way package objects were inserted when typechecking source and unpickling. The unpickling version was faulty. |
Match types defined in the scope of an opaque definition leak the underlying opaque type if used in separate compilation module.
Note: could be related to #12944
Compiler version
v3.0.2-RC2
Minimized code
See minimized branch at: https://github.com/soronpo/dottybug/tree/match_type_opaque_leak
main/scala/core/Foo.scala
main/scala/LeakFoo.scala
test/scala/Foo.scala
Output
Expectation
shouldFail
should generate a type-mismatch errorshouldWork
should compile fine.The text was updated successfully, but these errors were encountered: