Skip to content

Bad symbol is selected leading to ClassCastException. Regression from scala 2.13 #19711

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

Closed
jtjeferreira opened this issue Feb 17, 2024 · 2 comments · Fixed by #19719
Closed

Comments

@jtjeferreira
Copy link
Contributor

jtjeferreira commented Feb 17, 2024

Compiler version

Scala 3.3.2 (3.4.0 also affected)

Minimized code

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

case class Config(_config: String)

abstract class Foo(val config: Config) {
  def this(config: String) = {
    this(Config(config))
  }
}

class Bar(config: String) extends Foo(config) {
  def foo(): Unit = {
    config.getClass()
  }
}

new Bar("").foo() //This line will crash in prod

Output

Caused by: java.lang.ClassCastException: class Playground$Config cannot be cast to class java.lang.String (Playground$Config is in unnamed module of loader sbt.internal.BottomClassLoader @11415fc3; java.lang.String is in module java.base of loader 'bootstrap')
at Playground$Bar.config$accessor(main.scala:11)
	at Playground$Bar.foo(main.scala:13)
	at Playground$.<clinit>(main.scala:17)

Expectation

That code compiles and runs without crashing (like in scala 2.13)

@jtjeferreira jtjeferreira added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Feb 17, 2024
jtjeferreira added a commit to jtjeferreira/akka-persistence-jdbc that referenced this issue Feb 17, 2024
@SethTisue
Copy link
Member

minimized a bit further,

class Foo(val s: Any):
  def this(s: String) =
    this(0)
class Bar(s: String) extends Foo(s):
  def foo = s
Bar("").foo

java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String

odersky added a commit to dotty-staging/dotty that referenced this issue Feb 17, 2024
To qualify as a super-parameter alias, a parameter of a subclass has to be
passed to the primary constructor of the superclass.

Fixes scala#19711
@odersky
Copy link
Contributor

odersky commented Feb 17, 2024

How I fixed it:
I suspected from the bug description that something in the scheme of super parameter aliases went wrong. This scheme optimizes away duplicates of parameter fields in subclasses if they can be shown to be always aliases of a val parameter in a superclass. But I did not know anymore where that scheme was implemented. So I looked at the output at various phases. Typer and PostTyper and FirstTransform all looked OK, but at Erasure I saw that an accessor s$accessor was generated where it should not have been. I then searched for the $accessor in the codebase and found that it was the suffix of the semantic name category ParamAccessorName. I then searched for occurrences of that name and found phase ParamForwarding which implemented the faulty transform. ParamForwarding relied on info provided by method forwardParamAccessors in PostTyper. That method was clearly missing the condition that forwarders have to go through the primary constructor. Secondary constructors can call super with anything they choose, so without looking at their code we cannot assume anything.

@odersky odersky self-assigned this Feb 18, 2024
@Gedochao Gedochao added area:typer area:transform and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Feb 19, 2024
SethTisue added a commit that referenced this issue Feb 19, 2024
To qualify as a super-parameter alias, a parameter of a subclass has to
be passed to the primary constructor of the superclass.

Fixes #19711
@Kordyjan Kordyjan added this to the 3.4.2 milestone Mar 28, 2024
@Kordyjan Kordyjan modified the milestones: 3.4.2, 3.5.0 May 10, 2024
WojciechMazur pushed a commit that referenced this issue Jul 1, 2024
To qualify as a super-parameter alias, a parameter of a subclass has to be
passed to the primary constructor of the superclass.

Fixes #19711

[Cherry-picked e6b726b]
WojciechMazur pushed a commit that referenced this issue Jul 2, 2024
To qualify as a super-parameter alias, a parameter of a subclass has to be
passed to the primary constructor of the superclass.

Fixes #19711

[Cherry-picked e6b726b]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants