Description
Minimized example
class B(val y: Int):
println(y) // A warning is due here
foo()
def foo() = println(y)
class C(override val y: Int) extends B(10)
@main
def Test = new C(20)
Output
10
20
Expectation
The code above depends on subtle semantics of class parameters in constructors, for which the programmer should receive a warning.
As discussed in #15723 (comment), one possibility to issue the warning is:
Rule A: Issue a warning for the usage of an unqualified class parameter x
in the constructor (including usage in super constructor calls) if this.x
is overridden in a subclass.
This rule, however, is too coarse-grained, as programmers will get an annoying warning for the following code:
class B(val y: Int):
println(y) // should not issue a warning here
foo()
def foo() = println(y)
class C(override val y: Int) extends B(y)
Here is a better rule to avoid the spurious warnings in the above:
Rule B: Issue a warning for the usage of an unqualified class parameter x
in the constructor (including usage in super constructor calls) if its semantics deviate from that of this.x
.
The plan is to implement the rule in the initialization checker. Implementation of Rule B would require extending the abstract domain with a symbolic value in the spirit of symbolic execution.