Unfortunately, Julia does not specialize on keyword arguments, and therefore the actual type of ``rng`` is unknown when the compiler generates the code, thus resulting in big performance penalty.

Random number generating functions lie at the heart of many performance-critical applications, and therefore we should be very cautious about performance issues, and should ensure that no performance penalty is caused by failure of type inference.

I am wondering why you have to put ``rng`` as keyword argument. I think you can simply do
```julia
function bitarray_rand_fill!(B::BitArray, rng::AbstractRNG)
    ...
end
bitarray_rand_fill!(B::BitArray) = bitarray_rand_fill!(B, default_rng)
```
In this way, the type of each argument is known at compile time, and as a consequence, we get much more performant codes.