What's the correct approach to upgrade a contract using ERC7201

No, there are no state variables in this contract, only a struct definition!

This function takes a storage input argument, which means that when called, it receives that input as a "pointer" to storage, allowing it to modify the "pointed" data directly.

But that input argument isn't explicitly declared in this contract.

It is assumed to already reside in some storage slot, namely:

// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;