Error compiling @rescript/core with Rescript 11

Your example can be fixed by explicitly uncurrying:

Console.log("Hello, world!")

-Console.log(List.make(~length=1001, 1)->List.reduceReverse(0, (acc, item) => acc + item))
+Console.log(List.make(~length=1001, 1)->List.reduceReverse(0, (. acc, item) => acc + item))
1 Like

So there indeed issues with ReScript 11.0.1 and Core 1.1.0? Is really needed to modify the file in node_modules?

I’m having this issue in 2 different projects that were using rescript 10.1.4 and I upgrade them to rescript 11.1.0 :frowning: don’t know what is going on

@jihchi I’m using your starter template and your vite plugin, the uncurried is false like here: vitejs-template-react-rescript/rescript.json at 24450dea0f8752d5f828f918f0b8b9f5e644775c · jihchi/vitejs-template-react-rescript · GitHub

@fham the issue is that I don’t have this call directly in my code, is something with the Core or some other library that may be using this function.

@ashton As @fham suggested, it would be helpful for troubleshooting if you can create a minimal repo.

1 Like

Same Issue happened here: ReScript 11.1 uncurried issue with core package?
In that case it was rescript-classnames.

This situation isn’t great obviously. v12 will have Core inside of the compiler itself so the problem will go away, but we should do what we can to clear up the situation before too. Suggestions welcome.

1 Like

@jihchi oh sorry, I misunderstood, I thought that the repo you posted was exactly the minimal example. The main point is, with a fresh installation, I can’t reproduce the issue, so it’s something related to my code or one of the libraries I’m using, what makes difficult to create something “minimal”

Based on this post I tried to figure out if some other library was using some old version of rescript core, but it doesn’t be the case:

⋯/rsus on  main [✘!?] via  v18.20.2 took 836ms
❯ npm ls --all | grep "rescript/core"
├─┬ @rescript/core@1.3.0
│ ├─┬ @rescript/core@1.3.0
⋯/rsus on  main [✘!?] via  v18.20.2 took 921ms
❯ npm ls --all | grep "rescript"
vite-react-rescript-starter@1.0.0 /Users/matheus.ashton/dev/pessoal/rsus
├── @glennsl/rescript-fetch@0.2.0
├─┬ @jihchi/vite-plugin-rescript@6.0.0
│ ├── rescript@11.1.0 deduped
├─┬ @rescript/core@1.3.0
│ └── rescript@11.1.0 deduped
├─┬ @rescript/react@0.12.1
├─┬ rescript-auth0-react@1.0.0 -> ./../rescript-auth0-react
│ ├─┬ @rescript/core@1.3.0
│ │ └── rescript@11.1.0 deduped
│ ├─┬ @rescript/react@0.12.1
│ └── rescript@11.1.0
├─┬ rescript-vitest@1.4.0
│ ├── rescript@11.1.0 deduped
├── rescript-webapi@0.9.1
├── rescript@11.1.0

Everything seems to be using Rescript 11.1 and @rescript/core 1.3.0

Is v12 close to release?

No, it will take some time until v12 releases. There will probably be a alpha version in the first half of the year though.

What do you get from npm explain @rescript/core ?

@rescript/core@1.3.0
node_modules/@rescript/core
  @rescript/core@"^1.3.0" from the root project

@rescript/core@1.3.0
../rescript-auth0-react/node_modules/@rescript/core
  @rescript/core@"1.3.0" from rescript-auth0-react@1.0.0
  ../rescript-auth0-react
    rescript-auth0-react@1.0.0
    node_modules/rescript-auth0-react
      rescript-auth0-react@"^1.0.0" from the root project

that’s your own library that you link locally or something? Because I only see older versions of it published on npm.

1 Like

Yes, is my own library, I’m installing locally it with npm link

but it also has been updated to use @core 1.1.3 as npm shows, could be any type of dependency resolution error or some kind of dependency cache from npm?

I think I got the answer, not sure if interest you guys but I’ll leave here anyways in case someone has the same problem that I was having. I also created a minimal repro environment in this repo

The issue is:

Core__List module has a function defined reduceReverse:

let reduceReverse = (type a b, l: list<a>, acc: b, f) => {
  let len = length(l)
  if len < 1000 {
    reduceReverseUnsafe(l, acc, f)
  } else {
    A.reduceReverseU(toArray(l), acc, f)
  }
}

as you can see, the else branch does:

A.reduceReverseU(toArray(l), acc, f)

A is defined earlier as:

module A = {
  let makeUninitializedUnsafe = Belt_Array.makeUninitializedUnsafe
  let reduceReverseU = Belt_Array.reduceReverseU
  let reduceReverse2U = Belt_Array.reduceReverse2U
}

So in the end, we’re calling Belt_Array.reduceReverseU

Checking Belt_Array’s definition here we can see that it calls the function with the uncurry syntax explicitly: f(. r.contents, getUnsafe(a, i))

So, the whole issue is, if uncurried is set to false in rescript.json the compiler assumes that the function that the Core__List.reduceReverse is receiving as argument is curried, but Belt_Array only accepts uncurried functions, since it’s explicitly using the uncurried syntax to call it, so the compiler throws an error.

If you change uncurried to true in rescript.json, the exception goes away, because now the compiler assumes that the function passed to Core__List.reduceReverse is already uncurried and would have no issues when Belt__Array calls it with the uncurried syntax.

In summary, @rescript/core is not compatible with uncurried: false as long as we use Belt underneath.

I think this could be stated in a clearer way in the documentation.

CC: @fham @jihchi @tsnobip

1 Like

We just released 1.4.0 of Core that removes the internal dep on Belt. Could you try that?

3 Likes

Hey @zth thanks for the reply! I tested and it indeed seems to work, but it’s outputting another error now:

I’m not sure if uncurried changed something about optional parameters, but it seems not accepting the call that is done inside Core__Int.fromString where it calls the Core__Float.parseInt) without the radix.

Maybe we can benefit of the new syntax and instead of the switch we could do just Core__Float.parseInt(x, ~radix=?radix) or even Core__Float.parseInt(x, ~radix=radix) ?

@zth Actually, looking at the module itself and its interface, I can see that the function are defined equally in both:

here is @rescript/core/src/Core__Float.resi:

@val
external parseInt: ('a, ~radix: int=?) => float = "parseInt"

And here is @rescript/core/src/Core__Float.res

@val external parseInt: ('a, ~radix: int=?) => float = "parseInt"

From this part of the documentation, if the function type annotation has ~paramName: type=? the function implementation should have ~paramName: option<type> doesn’t it? Not sure how this works with the external keyword.

But besides that, I could see this:
image

We have a parseIntWithRadix that is deprecated and suggesting the usage of the parseInt with optional arguments, but isn’t this the exactly opposite what rescript recommends on the documentation?

Shouldn’t we “undeprecate” parseIntWithRadix and make parseInt receive only the integer and not an optional radix?

Core__Int.fromString could call Core__Float.parseInt(x) (which is per se a little odd to me, why the Int module would call the Float module to parse an Int value?) or Core__Float.parseIntWithRadix(x, ~radix)

Actually, newer versions won’t work anymore as stated in the Readme. The only way this could be fixed is to release a version 1.2.1 or something that gets only rid of the dependencies on Belt but does not introduce the new way of binding a function with trailing optional parameters instead of having multiple functions.

@zth not sure if we should go down that avenue, since uncurried will be the only mode in v12.

1 Like