I think the negative arity is actually necessary. Take the following example:

```
let tuple_sum_with_more (x, y, z) =
let sum = x + y + z in
fun a b -> sum + a + b
(* Prevent inlining/simplification *)
let f = Sys.opaque_identity tuple_sum_with_more
let s = f (1, 2, 3) 4 5
```

If we had used 3 as the arity of the tupled function, then the last application of `f`

would see a 3-argument application of a function of arity 3, and call the underlying function directly, with some unfortunate results.

On the other hand, if we used the real arity of 1, then the runtime wouldnâ€™t know how many code pointer fields there are in the closure (itâ€™s one code pointer for functions of arity 1 (or 0), and two otherwise, but the tupled functions need two code pointers). Itâ€™s less important since 4.12, as the arity field now also encodes information about the first environment slot so scanning the closure for GC doesnâ€™t need to look at the actual arity, but I think there is still a bit of code in the compactor which relies on this property.

I believe any negative arity would work (it could be -1 instead of -3 in this example), but I guess thereâ€™s no harm in storing the additional information.

As a side note, Flambda doesnâ€™t use the same compilation scheme and will never generate closures with negative arity. Instead, it generates a specialised version of the `caml_tuplify`

function for each tupled function, which is then allocated in a regular closure of arity 1. Going back to your example, `let triple_sum (x, y, z) = x + y + z`

is compiled to:

```
let triple_sum_direct x y z = x + y + z
let triple_sum (x, y, z) = triple_sum_direct x y z [@@inline always]
```

The same scheme could be used with Closure, but with a performance cost (the tuple allocation wouldnâ€™t be removed anymore, and there are a few corner cases where the function would be inlined currently but fall outside the threshold with this version).