Compound's original Governor Bravo module used the following function for casting votes with a reason:
function castVoteWithReason(uint proposalId, uint8 support, string calldata reason) external {
emit VoteCast(msg.sender, proposalId, support, castVoteInternal(msg.sender, proposalId, support), reason);
}
My assumption is that the VoteCast event was chosen not to be emitted inside castVoteInternal to save on gas, as that would require an extra memory copy (please correct me if I'm wrong). The down-side of this approach is that code is less modularized, as the event has to be explicitly emitted across all vote casting method variants.
OpenZeppelin, however, chose to go with the modular approach, embedding the reason string into the internal function:
function _castVote(
uint256 proposalId,
address account,
uint8 support,
string memory reason
) internal virtual returns (uint256) {
...
emit VoteCast(account, proposalId, support, weight, reason);
}
My question, then, is given that the calldata type is now allowed inside internal functions, why not use string calldata reason instead of string memory reason? Or would an extra memory copy be required in either case?