effekt icon indicating copy to clipboard operation
effekt copied to clipboard

Unbox requires a boxed type, but got B.

Open phischu opened this issue 1 month ago • 2 comments

The following program:

type Status[B] {
  Done(value: Int)
  More(state: B)
}

def main(): Unit = {
  Done(123) match {
    case Done(value) => value
    case More(task) => task()
  }
  ()
}

yields the error message Unbox requires a boxed type, but got B..

Desired behavior is either to accept the program and infer B to be instantiated with () => Int at {}, or reject the program with an error message like "could not infer type argument for B in Done(123)".

phischu avatar Nov 25 '25 21:11 phischu

One reason why we don't instantiate is here in a TODO comment: https://github.com/effekt-lang/effekt/blob/4946a1cd95911ed759f9042266fbe7efbdb767ed/effekt/shared/src/main/scala/effekt/Typer.scala#L556-L566

EDIT: It's interesting that we don't propagate the expected type here; in this example it's always None, even if you do val res: Int = .... We could still pass a expectedResult: Option[ValueType] since we know it from the aforementioned annotation...

jiribenes avatar Nov 26 '25 14:11 jiribenes

Best I can do without that is:

// ...
    case More(task) => task()
                       ^^^^
// [info] Type parameter(s) B of type B could not be inferred.
// Consider providing explicit type annotations where this type originates.

// [error] Unbox requires a boxed type, but got B.

where the only reasonable workaround I have is

// ...
    case More(task) =>
      def t: () => Int = task
      t()

jiribenes avatar Nov 26 '25 14:11 jiribenes