Skip to content

Wrong code generation/memory errors in generic lambda parameters #4168

@stefandd

Description

@stefandd

In the code below, when I define the lambda argument in filter() as box->A!, it works, but when I define it as this->A! it compiles and runs, but the lambda surprisingly does not get called at all.

use @printf[I32](fmt: Pointer[U8] tag, ...)

class ArrayLike[A: Any #read] // Array-like class with .filter() function
  embed _data: Array[A] = []

  new fromArray(a: Array[A]) =>
    var i = USize(0)
    while i < a.size() do
      try _data.push(a(i = i + 1)?) end
    end

  fun apply(i: USize): this->A ? => _data(i)?

  // works correctly | with box->A!, but is buggy with this->A!
  //                 v
  fun filter(f: {(this->A!): Bool}): FilterClass[A, this->ArrayLike[A]]^ =>
    FilterClass[A, this->ArrayLike[A]](this, f)

class FilterClass[A: Any #read, B: ArrayLike[A] #read]

  new create(array: B, f: {(B->A!): Bool}) =>
    try @printf((f(array(0)?).string() + "\n").cstring()) end

class Thingy

actor Main

  new create(env: Env) =>
    let a: ArrayLike[I32] = ArrayLike[I32].fromArray([0])
    let b: ArrayLike[Thingy] = ArrayLike[Thingy].fromArray([Thingy])
    let f1 = a.filter({(x) => true})
    let f2 = b.filter({(x) => true})

with fun filter(f: {(box->A!): Bool}) .. this outputs

true
true

with fun filter(f: {(this->A!): Bool}) .. this outputs

true
false

The false is likely bug: it means that the lambda is NOT called! It is worth pointing out that in a slightly different version of this, where the lambda was supposed to actually filter, most of the time no output was generated with the this->A! version but sometimes random characters appeared (memory corruption?!)

Metadata

Metadata

Assignees

Labels

triggers releaseMajor issue that when fixed, results in an "emergency" release

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions