It's not a problem with using rules in the def; it's a problem of whether x literally appears in the rhs or not.
When applying a definition where the pattern x_ on the lhs has been matched to an argument (e.g. 2), Mathematica looks to see if the pattern name x appears anywhere in the definition's rhs, substitutes the matched value for any x's it finds, then evaluates. Here, it looks at f[2] and matches 2 to x_, then looks at the rhs of the definition, and only sees a, /., and r (and no x). So, it doesn't substitute anything, and finishes its application of the definition. All further evaluation (of a /. r) "doesn't know about" the definition anymore. (In particular, it doesn't know about he value 2 that got matched to x, and x is now "just a symbol again".)
Further, when you use :=, the rhs you typed in is unevaluated, and the definition Mathematica learns is the replacement rule f[x_] :> a /. r. However, when you use =, the rhs is evaluated first, and then learned as a definition. So we start with f[x_] = a /. r, a /. r becomes 2x, then the definition that Mathematica learns is the rule f[x_] :> 2x. That's why cvgmt's solution in the comments (f[x_] = a /. r) works. See this for more about the difference between := and = :)
(Note: I omitted some of the technicalities when describing what rule Mathematica actually learns and how it uses the rule, but all in all, it behaves roughly like :>.)
f[x_] = a /. r. – cvgmt Jun 08 '22 at 15:15xliterally appears in the rhs or not. When applying a definition where the patternx_on the lhs has been matched to an argument, e.g.2, mathematica looks to see if the pattern namexappears anywhere in the definition's rhs, substitutes, then evaluates. Here it only seesa,/., andr, and nox, so it doesn't substitute anything and finishes its application of the definition. All further evaluation "doesn't know about" the definition anymore. Further... – thorimur Jun 09 '22 at 08:17:=, the rhs you typed in is unevaluated, and the definition mathematica learns is the replacement rulef[x_] :> a /. r. When you use=, the rhs is evaluated first, and then learned as a definition—so we start withf[x_] = a /. r,a /. rbecomes2x, then the definition that mathematica learns is the rulef[x_] :> 2x. That's why cvgmt's solution works. See this for more about the difference between:=and=:) – thorimur Jun 09 '22 at 08:21