The thing about the handling of different shapes is that they have idiosyncrasies. Resizing one side of a square resizes all of its sides; resizing one side of a rectangle resizes two out of four sides; resizing one side of an arbitrary quadrilateral only resizes the one.
These are very different abstractions, with different behaviors. Even though all shape functions technically use the same code, they're not conceptually doing the same thing. Linking these abstractions by way of a shared extracted functions is inviting bugs.
The thing about the handling of different shapes is that they have idiosyncrasies. Resizing one side of a square resizes all of its sides; resizing one side of a rectangle resizes two out of four sides; resizing one side of an arbitrary quadrilateral only resizes the one.
These are very different abstractions, with different behaviors. Even though all shape functions technically use the same code, they're not conceptually doing the same thing. Linking these abstractions by way of a shared extracted functions is inviting bugs.