> When "out" and "in out" parameters are distinguished, there is no need for the existence of constructors as a separate concept.
I don't agree with this. You can get I need to do things "post-init" with controlled types, or use a `return X : Thing do ... end return` block. Constructors help ensure invariants. You can make a type `is private` to prevent instantiation, only allowing creation via functions (sort of like Rust `new` associated functions), or initialization via an `out` param. It's OK but not perfect, but you can also tag on a `Type_Invariant` aspect if there are conditions which have to be met by a type. My big problem with Controlled types is that forces a type to be `tagged` (i.e. it has a vtable) which means it affects storage layout of values of that type, which isn't a problem in C++.
You can forbid copies by making something a `limited` type, but you'd have to write your own "Move" equivalent, and some of the containers have `Move` subprograms implemented to transfer contents. Limited types might elide the copy when returned from a function, but it's been a while since I looked at those rules.