Skip to content

moonc linker ICE with nested JsPromise[JsPromise[T]] #15

@bikallem

Description

@bikallem

Summary

The moonc linker crashes with Moonc.Basic_hashf.Make(Key).Key_not_found(_) when code produces a nested JsPromise[JsPromise[JsValue]] type. This happens when a .then() callback returns a JsPromise instead of a plain value.

Minimal reproduction

// moon.pkg
import { "bikallem/webapi" }
options("is-main": true, "supported-targets": ["js"])
// main.mbt
fn main {
  @webapi.window
  .fetch("http://example.com")
  .then(fn(response : @webapi.Response) {
    response.text().then(fn(body : String) -> @webapi.JsValue {
      println(body)
      @webapi.JsValue::undefined()
    })
  })
  |> ignore
}

moon check --target js passes, but moon build --target js crashes the linker:

Error: Moonc.Basic_hashf.Make(Key).Key_not_found(_)
moonc version: v0.8.2+8cca5f22a

Root cause

JsPromise::then[T, U] returns JsPromise[U]. When the callback returns JsPromise[JsValue], the result type is JsPromise[JsPromise[JsValue]] — a nested #external generic. The linker's hash table fails to look up this nested type key.

Workaround

Ignore the inner promise so the outer callback returns Unit:

fn main {
  @webapi.window
  .fetch("http://example.com")
  .then(fn(response : @webapi.Response) {
    response.text().then(fn(body : String) {
      println(body)
    })
    |> ignore  // outer callback returns Unit, not JsPromise
  })
  |> ignore
}

This builds successfully. Behavior is identical since JavaScript flattens nested promises at runtime.

Notes

  • Reproducible with moonc v0.8.2+8cca5f22a, moon 0.1.20260209
  • Not specific to fetch — any code producing JsPromise[JsPromise[T]] should trigger it
  • This is a moonc compiler bug, filed here for visibility since webapi's JsPromise::then signature makes it easy to hit

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions