Function signatures are deterministically calculated in the context of Solidity contracts. They are nothing but a keccak256
hash of the function name along with the parameter types.
For ex, if you function is transfer(address _recipient, uint256 amount)
, the signature would be keccak256 of transfer(address,uint256)
which would result in the following hash:
a9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b
Whereas, during run time the EVM uses function selectors to invoke a function call to a specific method. Function selectors are first 4 bytes (0xa9059cbb
from the above example) of the function signature. So the can be function selectors can collide, but function signatures can never be the same for 2 functions.
Some useful resources: