-
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
transparent inline leak underlying opaque types #13461
Comments
Too many elements at play here. Somebody more familiar with macros should take this on. |
Minimized to object Bar:
opaque type MyOpaque = Int
object MyOpaque:
transparent inline def apply(): MyOpaque = 1
object Foo:
import Bar._
val shouldFail: Int = MyOpaque()
val shouldWork: MyOpaque = MyOpaque() |
@odersky it seems that when we have a transparent inline we are refining the return type to the inlined expression. I thought we did not allow transparent inlines to be defined in a context where we have opaque types. |
This is intentional, using transparent means you want the result type to depend on the computed type on the right-hand-side which in this case is |
Then it seems we are missing the val shouldFail: Int = 1
val shouldWork: Bar.MyOpaque = 1 where we should probably get val shouldFail: Int = 1.asInstanceOf[Bar.MyOpaque & 1]
val shouldWork: Bar.MyOpaque = 1.asInstanceOf[Bar.MyOpaque & 1] |
In this case, we don't execute this branch d4e8f5d#diff-03b5fb619563f54fbceece0e370239c21e3908fada0a395dd2c4c3e5280bd3b6R1003 |
A similar case reported in #14305 class Example {
opaque type Index = Array[Int]
transparent inline def index(using index: Index): Index = index
}
object Usage {
def run(example: Example)(using example.Index): Unit = {
example.index.length
}
} |
I bumped against this issue myself as well. Now I'm wondering what should be considered a proper use case for a
package foo
trait Impl1
trait Impl2
object OpaqueScope:
opaque type Wrapper = Impl1
transparent inline def wrapper: Wrapper = new Impl1 {}
package bar
import foo.{Impl1, OpaqueScope}
val x: Impl1 = OpaqueScope.wrapper My original intention was that Wouldn't it then make sense to assume that when a usage of a |
I have hit this issue as well: https://scastie.scala-lang.org/j5yMFWwwQoStHQ2LIEtDUw object Test:
opaque type NegativeInt = Int
object NegativeInt:
transparent inline def apply(i: Int) =
if i < 4 then applyC(i) else applyR(i)
private def applyC(i: Int): NegativeInt = i
private def applyR(i: Int): Option[NegativeInt] = Some(i)
import Test.NegativeInt
val a: NegativeInt = NegativeInt(3) //fails I'm trying to use the following to create an apply method that, if data can be checked at compiletime, runs compiletime checks with potential error messages, otherwise pushes the check to runtime and returns |
I am also hitting what seems to be a variation of this problem. Adding my minimized use case. Compiler version3.4.1-RC1 Minimized code
|
We hit this same issue today during a conversation in the Discord server. Trying to solve the original problem, we reached this code: https://scastie.scala-lang.org/BalmungSan/DzlQjmPBTuSZ08PIXqtbmw/46 I am actually surprised this was originally reported more than 3 years ago. And, I don't think this is working as expected. |
Maybe @Gedochao can prioritize this since several different people have hit this time and again. |
Fully qualified result works.
from #20302 |
@som-snytt that doesn't seem to work here: https://scastie.scala-lang.org/BalmungSan/DzlQjmPBTuSZ08PIXqtbmw/54 unless I did something wrong. |
@BalmungSan it checks for opaque proxies first. I don't know yet the difference in this simple example, however; I posted it here as a surprise. |
Interestingly, fully qualified names cause an opposite bug: package i20302:
opaque type Opaque = Int
transparent inline def op: Opaque = 123
transparent inline def oop: i20302.Opaque = 123
object Main:
def main(args: Array[String]): Unit =
val o2: 123 = op // OK
val o3: 123 = oop // BUG: Does not compile Before inlining, the typer wraps the rhs of |
The
transparent inline
macro that exists within an opaque source can leak the underlying opaque type.Note that this does not occur if the macro is not transparent, or if the inline is not a macro.
Additionally, we require another pass through a transparent
leak
definition to expose this leak (in this example it is implemented withgiven ... with
, but that could be atransparent inline
that does the same thing).Compiler version
v3.1.0-RC1
Minimized code
Minimized project at: https://github.com/soronpo/dottybug/tree/transparent_opaque_leak
MyOpaque.scala
Leak.scala
Output
Expectation
No error.
The text was updated successfully, but these errors were encountered: