Skip to content

ClassCastExcpetion when inheriting from two traits that define conflicting vals #23061

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
alex-aua opened this issue Apr 28, 2025 · 0 comments
Labels
area:initialization itype:bug itype:soundness Soundness bug (it lets us compile code that crashes at runtime with a ClassCastException)

Comments

@alex-aua
Copy link

Compiler version

3.3.5, 3.6.4

Minimized code

trait Actor

class LoggingAdapter {
  def info: String = "LoggingAdapter"
}

class DiagnosticLoggingAdapter extends LoggingAdapter {
  override def info: String = "DiagnosticLoggingAdapter"
}

trait ActorLogging {
  val log: LoggingAdapter = new LoggingAdapter 
}

trait DiagnosticActorLogging extends Actor {
  val log: DiagnosticLoggingAdapter = new DiagnosticLoggingAdapter {}
}

trait MyDiagnosticActorLogging extends Actor with DiagnosticActorLogging {
  def redefLog: DiagnosticLoggingAdapter = log
}

trait FSM extends Actor with ActorLogging

class MyActor extends FSM with MyDiagnosticActorLogging {
  override val log: DiagnosticLoggingAdapter = redefLog
}

(new MyActor).log.info

Output

java.lang.ExceptionInInitializerError
....
Caused by: java.lang.ClassCastException: class Playground$LoggingAdapter cannot be cast to class Playground$DiagnosticLoggingAdapter (Playground$LoggingAdapter and Playground$DiagnosticLoggingAdapter are in unnamed module of loader sbt.internal.BottomClassLoader @79576d95)
	at Playground$MyActor.Playground$ActorLogging$_setter_$log_$eq(main.scala:27)
	at Playground$ActorLogging.$init$(main.scala:14)
	at Playground$MyActor.<init>(main.scala:27)
	at Playground$.<clinit>(main.scala:31)

Expectation

I would have expected a compile error somewhere instead of the Runtime issue.

(when compiling under 3.6.4 with -Wsafe-init the compiler warns at the line in MyActor about an unitialized access to log, compare this scastie https://scastie.scala-lang.org/kTVVbeCwSlOdwqO58ldS9w )

Background: what we would have originally liked to do is fix a compile error by disambiguating the inherited log) via

class MyActor extends FSM with MyDiagnosticActorLogging {
  override val log: DiagnosticLoggingAdapter = super[MyDiagnosticActorLogging].log
}

Combining super with vals, however, does not seem to be allowed (full scastie: https://scastie.scala-lang.org/eiogKgSTTnyCB3CFCggCXA)

(Side note: We stumbled across this while trying to minimize a slightly different case of a failed disambiguation attempt; I'll link to it as soon as my colleague reports it)

@alex-aua alex-aua added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 28, 2025
@Gedochao Gedochao added itype:soundness Soundness bug (it lets us compile code that crashes at runtime with a ClassCastException) area:initialization and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:initialization itype:bug itype:soundness Soundness bug (it lets us compile code that crashes at runtime with a ClassCastException)
Projects
None yet
Development

No branches or pull requests

2 participants