Open
Description
Compiler version
Reproduced on 3.7.1, 3.7.0, 3.3.6 LTS. Works correctly on 2.13.
Minimized code
//> using scala 3.7.0
//> using options -Wall -Werror -Wsafe-init
trait Interface {
def value: String
}
var baseInitialized = 0
class BaseClass extends Interface {
override def value: String = {
baseInitialized += 1
"hello"
}
}
def doIt() = {
var mixin1Initialized = 0
trait Mixin1 extends Interface {
private lazy val value_lazyval: String = {
mixin1Initialized += 1
super.value ++ " mixin1"
}
abstract override def value: String = this.value_lazyval
}
val derived = new BaseClass with Mixin1
println(derived.value)
println(mixin1Initialized == 1)
derived.value: Unit
println(mixin1Initialized == 1)
}
doIt()
https://scastie.scala-lang.org/jiipi0fQS7WH1lPdPP7bHw
Output
hello mixin1
true
false
should be
hello mixin1
true
true
Expectation
The value_lazyval
should be memoized but the body appears to get executed again on each invocation. Interestingly, this only happens if the mixin trait is a local class (comment out the doIt
function to test for yourself). The behaviour here is very insidious and a regression compared to Scala 2.13, where above snippet works as expected.