I would like to see an experiment where modules, their properties, and their dependencies are written down in a separate file.
For example, it would tell module main depends on ui, utils and json, ui on graphics (a third party library) utils on encrypt and IO (which are part of the standard library of the language), json on Streams (another part of the standard library).
It also could say graphics doesn’t use reflection, json is thread-safe and O(input size), utils is pure, encrypt is constant-time, and main isn’t restricted in any way.
The compiler would have to enforce both the dependencies (main couldn’t directly call functions in IO, for example) and the properties (if json uses shared state, it somehow must be properly protected with locks/atomics) (this may, in cases, be a research project. Some properties might be better served with a different or more limited language (that’s what dtrace does for its language, to guarantee it won’t loop forever)
That file would serve as documentation. Tools would exist to render it to svg; users would expect their IDE to do that, maybe even in editable form.
Advantage of separating that from the source files would be that it is harder to accidentally change that information. Spotting them in reviews would be trivial, history could be tracked, etc.
Maybe, the compiler could error when compiling a module where the documentation doesn’t say it’s thread-safe, but it still is, but I can see problems with that, too, where implementers don’t want to commit to something, but still do it. Maybe, we need 3-valued properties: “is thread safe”, ”is not thread-safe”, and “doesn’t want to commit to thread-safety”
Advantage of the compiler enforcing the properties is that they would remain true.
Yes, you can bolt a lot of that on top of about any existing language, but the language needs a culture of doing that. I think golang has shown that the design of a language can influence its culture.
As I said: “I would like to see an experiment”. I’m not sure I would really be happy with the results though. What if there’s that one function that logically belongs in encrypt, but can’t be made constant time? Do you really want to create a sister module for that one function?