Man this is a doozy of a problem.
I would start by noting the actual types passed to the different parameters of funny
, then work from there. So source
will be an Iterator<B>
, target
will be a MutableCollection<A>
, base
will be C
.
So then let’s work through our function. var result: R = base
… so base
is either S
or R
. So in our use case, S
or R
becomes C
.
for (value in source)
, source
is an Iterator<B>
, so each value
is B
. Not much we can really infer there.
result = how(result, value)
, now this is pretty interesting. This is clearly an accumulator function of some kind. Since we know result
is R
, and this how
function takes result
and returns result
, we know the signature is how: (R, ????) -> R
.
target.add(result)
, so this tells us that target
must be a MutableCollection<R>
, since result
is R
and you can add result
to target
.
So… now we have this:
fun <T, S : R, R> funny(
source: Iterator<????>,
target: MutableCollection<R>,
base: ????,
how: (R, ?) -> R
)
Looking at our example some more… var result: R = base
. Now if we know that target
is type R
, and in our example, R
is A
, since target
is wtf
, our mutable list of A
, base
is c
, an instance of our C
class, which extends A
. So similarly, base
must be of type S
, since S
extends R
.
fun <T, S : R, R> funny(
source: Iterator<????>,
target: MutableCollection<R>,
base: S
how: (R, ?) -> R
)
At this point, I’m assuming that source
and how
use T
, because otherwise it wouldn’t be used… and also, since in our example, R
is A
, S
is C
, B
cannot be R
or S
. Ergo… B
becomes our T
type.
fun <T, S : R, R> funny(
source: Iterator<T>,
target: MutableCollection<R>,
base: S
how: (R, T) -> R
)
I think that’s the answer. I haven’t tested my code though, so maybe I’m wrong. 
Does that explanation make sense? Were you able to follow my logic? It’s pretty confusing… especially since the classes are all single letters, like the types.