Skip to content
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

CCE returning AnyVal from concrete method calling super that abstracts over the AnyVal type #12809

Open
nafg opened this issue Jun 19, 2023 · 4 comments
Labels
fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) valueclass
Milestone

Comments

@nafg
Copy link

nafg commented Jun 19, 2023

Reproduction steps

Scala version: Scala 2, including 2.13.11, but going way back too

Tested on JVM and JS. Confirmed it works on Scala 3 (both)

Code is at https://github.com/nafg/reproduce-anyval-cce

class Inner
class Outer(val inner: Inner) extends AnyVal
trait Abstract[F] {
  protected def helper: F
  protected def method(): F = helper
}
trait Concrete extends Abstract[Outer] {
  override protected def helper: Outer = new Outer(new Inner())
}
trait Public extends Concrete {
  def method2(): Outer = super.method()
}

object instance extends Public

instance.method2()

This is a minimized version of a real world problem. I discussed it at https://discord.com/channels/632150470000902164/635668814956068864/1119201503937302610

Translation:

Name in minimized Real symbol
Inner japgolly.scalajs.react.callback.Trampoline
Outer japgolly.scalajs.react.callback.CallbackTo
Abstract japgolly.scalajs.react.extra.BroadcasterF
Abstract#helper japgolly.scalajs.react.util.Effect.UnsafeSync#traverse_
Abstract#method japgolly.scalajs.react.extra.BroadcasterF#broadcast
Concrete japgolly.scalajs.react.extra.Broadcaster
Concrete#helper japgolly.scalajs.react.util.EffectCallback.callback#traverse_
Public io.github.nafg.scalajs.react.util.PublicBroadcaster

Problem

It crashes at runtime with Exception in thread "main" java.lang.ClassCastException: class Outer cannot be cast to class Inner

Note that removing super. in method2 fixes it. Originally I was overriding the same method just to make it public.

@nafg
Copy link
Author

nafg commented Jun 19, 2023

If there is a workaround for the case of override def method() = super.method() I'd appreciate knowing it. I'd like to be able to turn a library-protected method into a subclass-public method.

@SethTisue SethTisue added the fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) label Jun 20, 2023
nafg added a commit to nafg/scalajs-react-util that referenced this issue Jun 22, 2023
@noresttherein
Copy link

I don't think it should compile at all, at least it would be consistent with how it works in general. In general, you can't provide a value class as a type parameter to a super class if that type is either returned from a method (directly, not wrapped), or used as a method argument. You get the annoying error of 'bridge method generated for <superclass.method> clashes with the method <subclass.method> itself because they both have the same signature after erasure'. Now, I don't think this is an unsolvable issue, but last time I inquired, nobody was in a hurry to change it.

@noresttherein
Copy link

noresttherein commented Jul 22, 2023

@nafg, if you'd like the same effect, you can go with 'poor man's opaque types` for Scala 2:

class Inner
type Outer //left abstract

def Outer(inner :Inner) :Outer = inner.asInstanceOf[Outer]

implicit class OuterExtension(val self :Outer) extends AnyVal {
   def inner :Inner = self.asInstanceOf[Inner]
    //any methods which would go in a value class Outer go here.
}

This trick is very useful exactly because it avoids both your problem and the problem of bridge method clashing with specialized override in a subclass.

@nafg
Copy link
Author

nafg commented Jul 23, 2023

Are you suggesting to rewrite scalajs-react that way?

@SethTisue SethTisue added this to the Backlog milestone Aug 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) valueclass
Projects
None yet
Development

No branches or pull requests

3 participants