Skip to content

Toplevel module M = await (P: S) compiles to a static import #8815

Closed

Description

@cristianoc

Found by adversarial experiments on semantic analysts.

What is broken

The parsetree and Ast_await describe await (M: S) with a module-type path S as a dynamic import:

let module handles that form (bs_builtin_ppx.ml#L417-L439). The toplevel Pstr_module case rewrites only the unconstrained form (L763-L794). module_expr_mapper then strips the await (L854-L856), so the module is imported statically.

Reproduction

P.res: let x = 1

Main.res:

module type S = {let x: int}
module A = await P
module B = await (P: S)
let f = async () => {
  module C = await (P: S)
  C.x
}

Commands (with Primitive_promise.res copied from the runtime and a one-line Primitive_module.res containing external import: 'a => promise<'a> = "%import", each compiled first with bsc -nopervasives):

bsc -nopervasives P.res > P.js
bsc -nopervasives -I . Main.res

Output at master:

let P = require("./p.js");
let A = await import("./p.js");
async function f() {
  return (await import("./p.js")).x;
}
let B = P;

Expected: B is a dynamic import like A and the local C, for example let B = await import("./p.js");, with no static require of P.

Introduced

ece8b14 already compiles it this way. The comments describing it as a dynamic import come from #8738 (23a4197).

Impact

Writing module M = await (P: S) at toplevel puts P in the static import graph, so it is not code-split, and nothing reports it. The same constrained form inside a function is a dynamic import. Either the toplevel case should handle a module-type path like let module does, or the comments should state the restriction.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions