Skip to content

ClassCastException when attempting to use structural refinement that returns a value class #19833

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

Open
steinybot opened this issue Feb 29, 2024 · 1 comment
Labels
area:value-classes Issues tied to value classes. itype:bug

Comments

@steinybot
Copy link
Contributor

steinybot commented Feb 29, 2024

Compiler version

3.4.0 Next, 3.3.2 LTS, 2.13.12

Minimized code

//import scala.language.reflectiveCalls
import scala.reflect.Selectable.reflectiveSelectable

class FunctionalComponent[P](val component: P => String) extends AnyVal

object View {
  val component = new FunctionalComponent[String]({ s => "Hello " + s })
}

type FunctionalComponentObject[P] = {
  val component: FunctionalComponent[P]
}

val obj: FunctionalComponentObject[String] = View
val component: FunctionalComponent[String] = obj.component

https://scastie.scala-lang.org/nHksLLQJR8GiiOws7Pt2rA

Output

java.lang.ClassCastException: class Playground$View$$$Lambda$12376/0x00007ff68d5a4208 cannot be cast to class Playground$FunctionalComponent 

Expectation

Ideally this should compile and run without any errors.

Does it need to cast? I would have thought that the compiler has already checked that View conforms to the refinement and so component is already known to be a FunctionalComponent.

If it does need to cast then is there any way for there to be a runtime check to tell whether it is boxed or unboxed? I'm guessing it is assuming that it is boxed when in fact it is not which is why there is a ClassCastException.

I found a lot of old Scala 2 issues such as scala/bug#6336 which seemed to restrict how value classes were used with refinements which seems less than ideal but if that is indeed the only answer it would be better to not compile than compile and fail at runtime.

@steinybot steinybot added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Feb 29, 2024
@WojciechMazur
Copy link
Contributor

I think it might be related to how value classes are implemented, these might expose some kind of unsoundness related to it.
Since it can be found in both Scala 2 and Scala 3 there is a chance that we won't be able to fix it in backward compatibile manner.

Scala 3-only workaround which works correctly is to use opaque types:

opaque type FunctionalComponent[P] = P => String
object FunctionalComponent:
  def apply[P](fc:  P => String): FunctionalComponent[P] = fc

I agree that it would be the best to make sure we can catch the invalid usage of value classess at compile time, maybe at least this part should be achievable.

@Gedochao Gedochao added area:value-classes Issues tied to value classes. and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:value-classes Issues tied to value classes. itype:bug
Projects
None yet
Development

No branches or pull requests

3 participants