June 12, 2021

One of the things I don't like about C++ is that signatures often end up being complex. Sadly, D2's signatures are even more complex (D1 had an edge on C++ there).

Why not simply move "linting" information to a separate line and keep the "first line" of function definitions clean.

E.g. to require the return value, a, b to have the same lifetime:

int myfunc(A a, ref T c)
lifetime(return,c.x)
{
  body
}

Or introduce a new operator £ that takes the lifetime of an object, which I think is even better:

int myfunc(A a, B b, ref T c)
require(£return==£a.x)
{
  body
}

This would also allow specifying destruction order

require(£b < £a.x)

Or are there things that needs to be expressed about life times that cannot work with such a scheme?

I also think a scheme like this should allow library authors to give names to individual requirements and invariants.

That would allow better error messages, maybe even custom error handlers, e.g.:

…
invariant outofbounds { tests }
…
require lifetimes (…)
…
__interpret_compilation_error outofbounds (context) {
   if (context.xyz such and such)
   return "This failed because..."
}