Block messages with transactions hashes instead of full transactions When a bitcoin node has the blockchain in sync, most transactions in incoming block messages may have been already received as standalone tx messages before.

With a block message with only transaction hashes, the receiving node could try to reassemble the full block with its unconfirmed transactions and just request the missing transactions to complete the block.

Since this way to save bandwidth looks too obvious, I'm guessing there must a reason to always include the transactions in block messages, even after downloading the blockchain.
There are probably several reasons, but it's mostly historic. There is no inherent problem with just sending transaction id's. There is a disadvantage too, though, namely increased latency, which is not necessarily a problem when doing an initial sync, but it is not wanted when a fresh new block is propagating.

In fact, this idea is part of BIP 37, which specifies a protocol extension for requesting filtered blocks. To avoid the increased latency, matching transactions that are not known to the server to be already known to the receiver, are sent immediately after the filtered block itself.

Edit: BIP152 compact blocks also use this idea, though they use shortened 48-bit transaction ids instead to save space.