Because of how accumulate (and accumulate2) is structured, we cannot iterate over just b, we need to include something like c(b, growth) for each point. For this, instead of passing b, we'll pass a list of vectors, which can be produced with:
with(x, pmap(list(b, growth), c))
# [[1]]
# [1] 100.0000000 0.0265944
# [[2]]
# [1] 110.00000000 0.07115916
# [[3]]
# [1] 120.00000000 0.03739895
# [[4]]
# [1] 130.00000000 0.07958855
# [[5]]
# [1] 140.00000000 0.08470159
# [[6]]
# [1] NA 0.005054528
# [[7]]
# [1] NA 0.04800139
# [[8]]
# [1] NA 0.08042529
# [[9]]
# [1] NA 0.05007772
# [[10]]
# [1] NA 0.04163871
With this, we can now accumulate:
fill_in2 <- function(prev, new) if (is.na(new[1])) prev[1]*(1+new[2]) else new[1]
options(pillar.sigfig = 5)
x %>%
mutate(b = accumulate(pmap(list(b, growth), c)[-1], .init = b[1], fill_in2))
# # A tibble: 10 x 3
# a b growth
# <int> <dbl> <dbl>
# 1 1 100 0.026594
# 2 2 110 0.071159
# 3 3 120 0.037399
# 4 4 130 0.079589
# 5 5 140 0.084702
# 6 6 140.71 0.0050545
# 7 7 147.46 0.048001
# 8 8 159.32 0.080425
# 9 9 167.30 0.050078
# 10 10 174.27 0.041639
The reason I do both pmap(..)[-1] and .init=b[1] is because with the default behavior of accumulate, the first element of .x is passed-through as-is; in this case, that would pass c(100, 0.0266) as the first return value, which is not what we want. To fix that, we remove that from the pmap'd list and add b[1] as the initialization value (.init=) of accumulate.
BTW: this is using the current value of growth applied to the previous value of b.
Another BTW: your use of fill_in used if_else. While it works, it is unnecessary and inappropriate. If one is looking to if an object that will always be length 1, then use if (and optionally else); if one is looking to condition on a vector of logicals, then use ifelse/if_else. While one can use if_else when you know that it will always always always be length 1, there is overhead and likely other things going on that are completely unnecessary (and in base R, ifelse has consequences and side-effects with non-trivial class data, so its use should be managed).
Since accumulate calls your function with exactly one row's worth of data at a time, the use of if is more appropriate.
Data
set.seed(123)
x <- tibble(a = c(1:10),
b = c(seq(100, 140, 10), rep(NA_real_, 5)),
growth = runif(10, 0.001, 0.09))