> Actually, looking at this whole approach here I think it is currently broken.
> The problem is that, in order to support the `rule ~> CaseClassCompanion` notation, we need a way to figure out the arity of the argument function *without* accessing `fun.vparams` or `fun.tpe`, because in the companion object case we don't have a `Function` in the tree. We only see the `Ident` and cannot access the `apply` method on the companion object here that the compiler will resolve to in a later phase.

Hm, you cought me :) I falsely assumed that arity of `CaseClassCompanion` is determined by `ts` and `e`. Apparantely this is only true when `CaseClassCompanion` consumes everything from value-stack that has been pushed by current rule. This simple example breaks this assumption:

```Scala
case class SomeCaseClass(a: String)
rule { capture(ANY) ~ capture(ANY) ~> SomeCaseClass }
```

Two strings will be popped out of value-stack and be given to `SomeCaseClass` causing compile-time error.

> We need logic here that determines the arity of the argument function *without* matching `$f` against anything!
> Luckily there is a way to do it: By inspecting `$g` here we should be able to do it.

Definitely only `$g` is not enough. For example, 

```Scala
case class SomeCaseClass1(a: String)
case class SomeCaseClass2(a: String, b: String)

def InputLine: Rule[HNil, String :: String :: String :: SomeCaseClass1 :: HNil] = rule {
  capture(ANY) ~ capture(ANY) ~ capture(ANY) ~ capture(ANY) ~>
    SomeCaseClass1
}

def InputLine: Rule[HNil, String :: String :: SomeCaseClass2 :: HNil] = rule {
  capture(ANY) ~ capture(ANY) ~ capture(ANY) ~ capture(ANY) ~>
    SomeCaseClass2
}
```

causes same calculation process. I do not see other ways to determine arguments of `f` rather then investigating `Out` of `$g`. We need to figure out what was consumed in `Out`, and then subtract this set from `Ops` type classes set. Another way is to determine consumed values from shape of result type of `apply` (particularly `O` in `Rule[I, O]`). After all that type juggling we still would have two sub-cases as `ops{0,1,2,3,4}` shape differs from `ops`'s one.

I suggest to add another implicit argument to `apply`. This could be `shapless.Nat` telling how many arguments are there in `f`. Or even better: implicit value of type that has one-to-one correspondence to `f` signature.

Code is [here](https://github.com/alexander-myltsev/parboiled2/blob/wip/case-class-apply/main/src/main/scala/org/parboiled2/Rule.scala#L166).

WDYT?