Skip to content

Submodule functor call is curried, but the target function is uncurried #7245

Closed
@dsiu

Description

@dsiu

I am porting bs-bastet to modern ReScript (v12+) (WIP at https://github.com/dsiu/rescript-bastet/tree/rescript-v12)

In rescript@12.0.0-alpha.7 (alpha.4 and later), the generated js for nested module functor invocation is incorrect.

The line:

let EQ = M.Eq(IntEq)(ArbitraryInt);

is assuming M.eq is curried while M.eq is defined as:

function Eq(E, A) {
  let suite = name => "suite: " + name;
  return {
    suite: suite
  };
}

let M = {
  Eq: Eq
};

which clearly isn't curried.

The error is:

{
  "message":"M.Eq(IntEq) is not a function. (In 'M.Eq(IntEq)(ArbitraryInt)', 'M.Eq(IntEq)' is an instance of Object)",
  "line":54,
  "column":21,
  "stack":"eval code@\neval@[native code]\n@about:srcdoc:39:20"
}

In rescript@11, the error line was compiled to :

let EQ = Curry._2(Eq, IntEq, ArbitraryInt);

which runs correctly.

Playground link for test code

Test Code

module type TEST = {
  type test
}

module type ARBITRARY = {
  type t
  type arbitrary<'a>
}

module type QUICKCHECK = {
  type t
  type arbitrary<'a>
}

module Interface = {
  module type EQ = {
    type t

    let eq: (t, t) => bool
  }
}

module Make = (T: TEST, Q: QUICKCHECK with type t = T.test) => {
  type t
  type arbitrary<'a>

  module Eq = (
    E: Interface.EQ,
    A: ARBITRARY with type t := E.t and type arbitrary<'a> := Q.arbitrary<'a>,
  ) => {
    let suite = name => "suite: " ++ name
  }
}

module IntWithTest = (
  T: TEST,
  Q: QUICKCHECK with type t = T.test,
  A: ARBITRARY with type t := int and type arbitrary<'a> := Q.arbitrary<'a>,
) => {
  module IntEq: Interface.EQ = {
    type t = int

    let eq = (a, b) => Int.equal(a, b)
  }
  module M = Make(T, Q)
  module EQ = M.Eq(IntEq, A)
}

module ArbitraryInt: ARBITRARY with type t = int and type arbitrary<'a> = array<'a> = {
  type t = int
  type arbitrary<'a> = array<'a>
}

module JsQuickCheck = {
  type t = int
  type arbitrary<'a> = array<'a>
}

module MochaTest = {
  type test = int
}

module TestInt = IntWithTest(MochaTest, JsQuickCheck, ArbitraryInt)

TestInt.EQ.suite->Console.log
// Generated by ReScript, PLEASE EDIT WITH CARE


let Interface = {};

function Make(T, Q) {
  let Eq = (E, A) => {
    let suite = name => "suite: " + name;
    return {
      suite: suite
    };
  };
  return {
    Eq: Eq
  };
}

function IntWithTest(T, Q, A) {
  let eq = (a, b) => a === b;
  let IntEq = {
    eq: eq
  };
  let Eq = (E, A) => {
    let suite = name => "suite: " + name;
    return {
      suite: suite
    };
  };
  let M = {
    Eq: Eq
  };
  let EQ = M.Eq(IntEq)(A);
  return {
    IntEq: IntEq,
    M: M,
    EQ: EQ
  };
}

let ArbitraryInt = {};

let JsQuickCheck = {};

let MochaTest = {};

function eq(a, b) {
  return a === b;
}

let IntEq = {
  eq: eq
};

function Eq(E, A) {
  let suite = name => "suite: " + name;
  return {
    suite: suite
  };
}

let M = {
  Eq: Eq
};

let EQ = M.Eq(IntEq)(ArbitraryInt);

let TestInt = {
  IntEq: IntEq,
  M: M,
  EQ: EQ
};

console.log(EQ.suite);

export {
  Interface,
  Make,
  IntWithTest,
  ArbitraryInt,
  JsQuickCheck,
  MochaTest,
  TestInt,
}
/* EQ Not a pure module */

Thank you for filing! Check list:

  • Is it a bug? Usage questions should often be asked in the forum instead.
  • Concise, focused, friendly issue title & description.
  • A minimal, reproducible example.
  • OS and browser versions, if relevant.
  • Is it already fixed in master? Instructions

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