am i supposed to put it in .res or .ressi files, or both?
putting it in X.res makes function calls inside X.res inlined (can tell in X.res.js), but other modules using X do not seem to inline the calls. putting it in X.resi does nothing anywhere.
You’re supposed to put @inline annotations in both .res and .resi files, if you use an interface file and don’t add the annotation there too, the compiler simply can’t know the implementation required @inline.
Beware though, @inline doesn’t work with functions for example.
ok apparently @inline works with functions indeed!
As you can see in this example, given the annotation is only present in the .res file, it’s only inlined inside the module, not if you use in outside of it.
If you want to inline things outside of the module, you should add @inline to the .resi file too.
The compiler has an internal experimental flag -bs-cross-module-opt which is off by default.
I think it leads to some errors in some cases but you could try to add
npm create rescript-app@latest
> select Command Line
> select rescript12-beta3
Add src/Foo.res:
@inline let a=(x, y)=>x+y
@inline let b=(x, y, z)=>a(a(x, y), z)
Add src/Foo.resi:
@inline let a:(int, int)=>int
@inline let b:(int, int, int)=>int
Modify src/Demo.res:
Console.log("Hello, world!")
let foo = Foo.b(1, 2, 3)
Inspect .res.mjs files:
File Foo.res.mjs:
// Generated by ReScript, PLEASE EDIT WITH CARE
function a(x, y) {
return x + y | 0;
}
function b(x, y, z) {
return (x + y | 0) + z | 0;
}
export {
a,
b,
}
/* No side effect */
Notice how a has be inlined inside b correctly
File Demo.res.mjs:
// Generated by ReScript, PLEASE EDIT WITH CARE
import * as Foo from "./Foo.res.mjs";
console.log("Hello, world!");
let foo = Foo.b(1, 2, 3);
export {
foo,
}
/* Not a pure module */
Notice how Foo.b has not be inlined
Adding -bs-cross-module-opt does nothing
Removing @inline from Foo.resi optimizes Demo.res.mjs to say let foo = 6 (so the @inline directive actually prevents optimization in this case, in my codebase it does nothing because i’m not using constants)
Removing @inline from Foo.res apparently does nothing in this example, but in my codebase, it prevents a from being inlined into b
This is not an optimization. This is an edge-case feature for folks who absolutely need particular values inlined for a JavaScript post-processing step, like conditional compilation. Beside the difference in code that the conditional compilation might end up outputting, there’s no performance difference between inlining and not inlining simple values in the eyes of a JavaScript engine.