-
Notifications
You must be signed in to change notification settings - Fork 469
Closed
Description
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.
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.OS and browser versions, if relevant.Is it already fixed in master? InstructionsTo pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel.
Activity
[-]Sub module functor invocation is generated incorrectly with curried sematic while the target function definition is generated as uncurried[/-][+]Submodule functor call is curried, but the target function is uncurried[/+]simplified repo for reproducing a rescript@v12.0.0-alpha.7 module fun…
simplified repo for reproducing a rescript@v12.0.0-alpha.7 module fun…
simplified repo for reproducing a rescript@v12.0.0-alpha.7 module fun…
cristianoc commentedon Jan 27, 2025
Here's a small example:
produces
Seems like a certain level of nesting is required to observe this.
dsiu commentedon Feb 2, 2025
@cristianoc : is this issue hard to fix? it was working on v12-alpha.3 and before so the bug was introduced recently. thanks a lot.
cristianoc commentedon Feb 2, 2025
Perhaps one could always emit functors as functions taking one argument at a time, unless there are some issue that could come with that.
Experiment with emitting functors as 1 arg at a time
cristianoc commentedon Feb 2, 2025
Something like this: #7273
If it works and it is safe, one can explore further.
cristianoc commentedon Feb 5, 2025
@dsiu could you try to install the package from CI and see if it works for you?
dsiu commentedon Feb 5, 2025
@cristianoc sure thing. Will revert back once I tested it. Thanks!
dsiu commentedon Feb 6, 2025
@cristianoc, I'm happy to report that #7273 fixes the problem. I ran it against my larger code base, and it only changes the module functor invocations, not any other code. I think it is good to go.
Thanks again.
Experiment with emitting functors as 1 arg at a time