> I‘d prefer a macro-like approach to generics where generic parameters are unconstrained like interface{} until they are used inside the function with constrained operators/function calls, which define the limitations for the parameters.
That sounds awfully like how C++ templates work, and I think that it’s pretty much universally agreed that that approach is not ideal due to the potential for supremely terrible error messages (among other drawbacks, probably). Contracts allow for type checking at the call site, which is significantly more user-friendly.
Compiler errors and their quality are fundamentally an implementation issue. I‘m talking about the design of the language and what the user has to deal with all the time, not just in the error case. Designing primarily for beautiful error messages is a flawed concept IMO.
> Compiler errors and their quality are fundamentally an implementation issue.
I don't really agree here; language design can place constraints on the quality of errors emitted by implementations. There's a reason Concepts are such a widely desired feature in C++, even though template errors now are vastly better than they were in the past --- there's only so much you can do with the language in its current state.
> I‘m talking about the design of the language and what the user has to deal with all the time, not just in the error case.
I'm inclined to say that fixing/avoiding type errors is likely to be far closer to what programmers have to deal with all the time than having to write contracts, especially for library types.
In addition, it's not just the error case that's involved here. If you're writing generic code with constraints on the involved type(s), those constraints are probably going to have to be documented somewhere anyways. Why not write them in your source code where the compiler can help?
> Designing primarily for beautiful error messages is a flawed concept IMO.
I'm not saying that the design has to be primarily for beautiful error messages; it's just that useful error messages are important and whatever design emerges should try to enable helpful error messages.
That sounds awfully like how C++ templates work, and I think that it’s pretty much universally agreed that that approach is not ideal due to the potential for supremely terrible error messages (among other drawbacks, probably). Contracts allow for type checking at the call site, which is significantly more user-friendly.