> The generic functions with the local type inference really cut down on the verbosity compared to Java/C++.



The reduced verbosity also comes from the D standard library Phobos being designed around Ranges instead of single iterators as in most C++ (there are ranges in the Boost C++ libraries, but their usage is not common).





> it's guaranteed that x < width and y < height, but to type that, your type system needs to understand modular arithmetic (not to mention the network of invariants between all the functions/variables)...



D language doesn't have dependent types, but it already performs a limited amount of similar inferences, called value range propagation. This means in the following program the line with 'b' is accepted, but the line with 'c' is statically refused, because it could lose some bits of the result value:

void main(string[] args) { uint a = 6000 + args.length; // Run-time value. ubyte b = a % 200; // OK. ubyte c = a % 300; // Complation error. ushort d = b + 65_280; // OK. ushort e = b + 65_281; // Complation error. }

This feature looks simple, and in many cases you don't see it, but it's refined, and it's one of the many less visible features of D. To keep the compiler simple the D specs don't require D compilers to perform such analysis across different lines. So in the DMD compiler it's done only on the current line. That's why the line with 'e' raises a compilation error, despite it can't overflow, because across lines it forgets b can't be more than 199.