ether.js you could call
contract.connect(<signer>) to change the context, in other words
This signer should be a wallet/account, it could not be another contract. However when inside your contract this contract calls another contract
msg.sender would be an address of the contract caller – not an address which was defined during the initial call, e.g.
It might be important during
ERC721 token approve call: we could approve one address, but eventually authorized
ERC721 token function would be called by deployed contract which would end up with revered tx as this address has not been approved.
msg.sender it is an address of contract caller - it would be a user's address who calls the contract or the contract's address who calls another contract despite on the origin caller is the user.