> This is just objectively false. Constraints liberate and liberties constrain.
You are completely wrong here. Flexibility by definition means an increase in the allowed degrees of freedom in one or more axes which in turn allows one to mix and match feature sets to express more design concepts (eg. Multi-paradigm). Your second line is a silly slogan which presumably means constraints make the job of picking one choice from a set easier due to less thought needed. It is applicable to inexperienced developers but certainly not to experienced ones who need all the flexibility that a language can give.
> As someone who understands variance etc quite well, my answer is to simply not have subtypes. You absolutely do not need inheritance subtyping to build production software. (Rust has subtyping and variance only for lifetime parameters, and that's confusing enough.)
You have not understood the example. Variance is used to constrain types but pre/post are predicates relating subsets of values from the types; this constrains the state space (cartesian product of the types) itself. Second, your statement not to use subtyping is silly. Subtype relationships arise naturally amongst concepts in any non-trivial system which you can group in a hierarchy based on commonality (towards the top) and variability (towards the bottom). Inheritance is just a direct way of expressing it.
> Inheritance is only traditional because C++ and Java made it so. I think it's been a colossal mistake.
Statements like these betray an ignorance of the subject. I have already shown that Inheritance can be used for different purposes of which Subtyping in the LSP sense is what everybody agrees on. The other uses need experience and discipline but are very powerful when done clearly. Inheritance was first introduced in Simula67 based on a idea presented by Tony Hoare in 1966. C++ popularized it and others simply copied it. See wikipedia for more details - https://en.wikipedia.org/wiki/Inheritance_(object-oriented_p...
PS: This discussion reminded me of "The Blub Paradox" by Paul Graham (https://paulgraham.com/avg.html) which i think most Rust evangelicals suffer from. Just from my cursory look at Rust i have seen nothing compelling to want me to study it in depth over my preferred language of C++. With the addition of more features into "Modern C++" to support Functional Programming it has become even more flexible and powerful albeit with a steeper learning curve.
> Your second line is a silly slogan which presumably means constraints make the job of picking one choice from a set easier due to less thought needed
That is absolutely not what it means, and it is not a silly slogan — it is a basic law of reality.
As an example, if your build system is monadic (build nodes can add new nodes dynamically) then the number of nodes in it is not known upfront. If the build system is not monadic, the number of nodes is determined at the start of the build process.
As another example, the constraints that Rust sets around & and &mut mean that the compiler can do really aggressive noalias optimizations that no one would even dream about doing in C or C++.
See https://m.youtube.com/watch?v=GqmsQeSzMdw for more examples.
> It is applicable to inexperienced developers but certainly not to experienced ones who need all the flexibility that a language can give.
I'm quite an experienced developer, and I've tended to use more constrained languages over time. I love the fact that Rust constrains me by not having uncoordinated shared mutable state.
> This discussion reminded me of "The Blub Paradox" by Paul Graham (https://paulgraham.com/avg.html) which i think most Rust evangelicals suffer from
At Oxide we use Rust and would never have been able to achieve this level of rigor in C++. Hell, try writing anything like my tool https://nexte.st/ in C++ (be sure to get the signal handling exactly right). Rust tooling is at a completely different quality level from earlier-generation languages.