Skip to content

Regression: Lazy val in local mixin trait is not memoized #23452

Open
@tschuchortdev

Description

@tschuchortdev

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions