Skip to content

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

Open
@alex-aua

Description

@alex-aua

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:initializationitype:bugitype:soundnessSoundness bug (it lets us compile code that crashes at runtime with a ClassCastException)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions