That is exactly the use case for Update
although the documentation about it won't give you in depth insights.
Shortly, once evaluated expressions are internally marked as such and won't undergo reevaluation for efficiency purposes. Unless something triggers them, like Update
.
validQ[_] = True;
Update[func];
{foo, func[a]}
{a, a}