Dlang + compile-time contracts

Marco Leise via Digitalmars-d digitalmars-d at puremagic.com
Mon Jul 31 10:54:04 PDT 2017


Coming from D.learn where someone asked for some automatism to
turn runtime format strings to `format()` into the equivalent
`format!()` form automatically to benefit from compile-time
type checks I started wondering...

The OP wasn't looking for other benefits of the template
version other than argument checking and didn't consider the
downsides either. So maybe there is room for improvement using
runtime arguments.

So let's add some features:
1) compile-time "in" contract, run on the argument list
2) functionality to promote runtime arguments to compile-time


string format(string fmt)
in(ctfe) {
  // Test if argument 'fmt' is based off a compile-time
  // readable literal/enum/immutable
  static if (__traits(isCtfeConvertible, fmt))
  {
    // Perform the actual promotion
    enum ctfeFmt = __traits(ctfeConvert, fmt);
    static assert(ctfeFmt == "%s", "fmt string is not '%s'");
  }
}
body
{
  return "...";
}


Note that this idea is based on existing technology in the
front-end. Compare how an alias can stand in for a CT or RT
argument at the same time:


void main()
{
	const fmt1 = "%x";
	auto fmt2 = "%s";
	aliasTest!fmt1;
	aliasTest!fmt2;
}

void aliasTest(alias fmt)()
{
	import std.stdio;
	static if (__traits(compiles, {enum ctfeFmt = fmt;}))
		// "Promotion" to compile time value
		enum output = "'fmt' is '" ~ fmt ~ "' at compile-time";
	else
		string output = "'fmt' is '" ~ fmt ~ "' at runtime";
	writeln(output);
}


This prints:
'fmt' is '%x' at compile-time
'fmt' is '%s' at runtime

For technical reasons a compile-time "in" contract can not
work in nested functions so all the CTFE contracts need to be
on the top level, user facing code. That means in practice
when there are several formatting functions, they'd extract
the implementation of the compile-time contract into separate
functions. I have no idea how exactly that scales as the
`static if (__traits(isCtfeConvertible, …))` stuff has to
remain in the contract. (It's probably ok.)

Extending the CTFE promotion to any variables that can be
const-folded is not part of this idea as it leaves a lot of
fuzzyness in language specification documents and results in
code that produces errors in one compiler, but not in another.
Since some people will still find it beneficial it should be a
compiler vendor extension and print a warning only on contract
violations.

</braindump>

-- 
Marco



More information about the Digitalmars-d mailing list