I've spent some more time on this patch, and now it passes all the regression tests. But I had to hack explain.c and ruleutils.c to make the varprefix stuff work as it did before, which is not great.
I've realized that I made a mistake in the v4 patch: If there are join alias vars in the targetlist and HAVING clause, we should first flatten them before replacing the grouped variables involved there with grouping-RTE Vars. To fix this issue, I decide to merge the newly added function substitute_group_exprs into check_ungrouped_columns by changing check_ungrouped_columns to also perform the replacement, which is Tom's initial suggestion I think.
Now it seems that 'check_ungrouped_columns' is no longer an appropriate name for the function. So I rename it to 'substitute_grouped_columns'. But I'm open to other names if there are any suggestions.