Because they have different semantics. Contracts are generic over multiple types and as /u/munificent mentioned elsewhere, they allow you to write code that enforces homogeneity. You can write a generic function that takes a slice of elements that have a Foo() method and all instances in the slice will have the same concrete type. This would allow the compiler to easily specialize those function calls, so no virtual function overhead. This means we could have an efficient, straightforward sort implementation that performs as well as a hand rolled implementation.
Agreed that devirtualization exists and improves performance, but it doesn’t address the semantic problem in that interfaces are about heterogeneity (and thus dynamic dispatch) while contracts are about homogeneity (which naturally lends itself to static dispatch). Additionally, devirtualization is a lot harder to implement (at least with any sort of useful comprehensiveness) as the compiler needs to prove to itself that the concrete type never varies which implies plumbing information across compilation units and (I think) breaking independent compilation of compilation units or at least making compilation dependent on some earlier whole-program-analysis pass.