www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - compile-time checked format strings

reply kdevel <kdevel vogtner.de> writes:
occasion: 
http://forum.dlang.org/thread/mutegviphsjwqzqfouhs forum.dlang.org?page=3#post-mailman.2136.1515709204.9493.digitalmars-d-announce:40puremagic.com

dmd checks the types but does not count the arguments.

ctcfs.d
```
import std.stdio;
import std.math;

void unit (T) ()
{
    auto pi = 4 * atan (T (1));
    writefln!"%30.24f" (pi, pi); // no error!
    writefln!"%30.24f %30.24f" (pi, pi); // OK
//   writefln!"%30.24d %30.24f" (pi, pi); // OK:  "incompatible 
format character
    writefln!"%30.24f %30.24f %30.24f" (pi, pi); // no error
}

void main ()
{
    unit!float;
}
```

$ dmd ctcfs.d
$ ./ctcfs
     3.141592741012573242187500
     3.141592741012573242187500     3.141592741012573242187500
     3.141592741012573242187500     3.141592741012573242187500

std.format.FormatException /.../dmd2/linux/bin64/../../src/phobo
/std/format.d(479): Orphan format specifier: %f
----------------
/.../dmd2/linux/bin64/../../src/phobos/std/exception.d:615 pure 
 safe bool 
std.exception.enforceEx!(std.format.FormatException).enforceEx!(b
ol).enforceEx(bool, lazy immutable(char)[], immutable(char)[], ulong) [0x44503c]
/.../dmd2/linux/bin64/../../src/phobos/std/format.d:479  safe 
uint std.format.formattedWrite!(std.stdio.File.LockingTextWriter, 
char, float, float).formattedWrite(ref 
std.stdio.File.LockingTextWriter, const(char[]), float, float) 
[0x44c436]
/.../dmd2/linux/bin64/../../src/phobos/std/stdio.d:1496  safe 
void std.stdio.File.writefln!(char, float, 
float).writefln(const(char[]), float, float) [0x44c340]
/.../dmd2/linux/bin64/../../src/phobos/std/stdio.d:3797  safe 
void std.stdio.writefln!(char, float, 
float).writefln(const(char[]), float, float) [0x44c2b7]
/.../dmd2/linux/bin64/../../src/phobos/std/stdio.d:3791  safe 
void std.stdio.writefln!("%30.24f %30.24f %30.24f", float, 
float).writefln(float, float) [0x44da27]
ctcfs.d:10  safe void ctcfs.unit!(float).unit() [0x443673]
ctcfs.d:15 _Dmain [0x443614]
Jan 13
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 13 January 2018 at 19:15:49 UTC, kdevel wrote:
 dmd checks the types but does not count the arguments.
so note that dmd doesn't actually do any checks here - it is all done in library code. The implementation is amusingly simple: https://github.com/dlang/phobos/blob/master/std/format.d#L5803 try format(...) catch(Exception) trigger compile time error. But, since float format doesn't work at compile time, this method doesn't actually work to catch any float-related problems except mismatching format characters! For ints, it catches all that, but for float, it just bails out of the check as soon as it actually *succeeds* - because that kills CTFE. We should just put in a fake stub float printer to hack this past for checking purposes.
Jan 13
next sibling parent Basile B. <b2.temp gmx.com> writes:
On Saturday, 13 January 2018 at 19:40:09 UTC, Adam D. Ruppe wrote:
 On Saturday, 13 January 2018 at 19:15:49 UTC, kdevel wrote:
 dmd checks the types but does not count the arguments.
so note that dmd doesn't actually do any checks here - it is all done in library code. The implementation is amusingly simple: https://github.com/dlang/phobos/blob/master/std/format.d#L5803
Yeah there's already an interesting issue about this https://issues.dlang.org/show_bug.cgi?id=17381
Jan 13
prev sibling parent kdevel <kdevel vogtner.de> writes:
On Saturday, 13 January 2018 at 19:40:09 UTC, Adam D. Ruppe wrote:
 For ints, it catches all that, but for float, it just bails out 
 of the check as soon as it actually *succeeds* - because that 
 kills CTFE.
Confirmed. Thanks! args.d ``` import std.stdio; void main () { // writefln!"%2.2d %2.2d" (1); // OK: Orphan format specifier // writefln!"%2.2d" (1, 2); // OK: Orphan format arguments: } ```
Jan 13