Thread overview
writef, compile-checked format, pointer
Aug 09, 2021
novice2
Aug 09, 2021
Patrick Schluter
Aug 09, 2021
Bastiaan Veelo
Aug 09, 2021
Ali Çehreli
Aug 09, 2021
Adam D Ruppe
Aug 09, 2021
Ali Çehreli
Aug 10, 2021
nov
Aug 10, 2021
Tejas
Aug 10, 2021
Ali Çehreli
August 09, 2021

format!"fmt"() and writef!"fmt"() templates
with compile-time checked format string
not accept %X for pointers,

but format() and writef() accept it

https://run.dlang.io/is/aQ05Ux

void main() {
    import std.stdio: writefln;
    int x;
    writefln("%X", &x);  //ok
    writefln!"%s"(&x);  //ok
    //writefln!"%X"(&x);  //compile error
}

is this intentional?

August 09, 2021

On Monday, 9 August 2021 at 19:38:28 UTC, novice2 wrote:

>

format!"fmt"() and writef!"fmt"() templates
with compile-time checked format string
not accept %X for pointers,

but format() and writef() accept it

https://run.dlang.io/is/aQ05Ux

void main() {
    import std.stdio: writefln;
    int x;
    writefln("%X", &x);  //ok
    writefln!"%s"(&x);  //ok
    //writefln!"%X"(&x);  //compile error
}

is this intentional?

Yes. %X is to format integers. Runtime evaluation of a format string does not allow for type checking. When using the template, the evaluation can be thorough and the types can be checked properly. You have 2 solutions for your problem, either a type cast

writefln!"%X"(cast(size_t)&x);

or using the generic format specifier that will deduce itself the format to using depending in the passed type.

writefln!"%s"(&x);
August 09, 2021

On Monday, 9 August 2021 at 22:01:18 UTC, Patrick Schluter wrote:

>

On Monday, 9 August 2021 at 19:38:28 UTC, novice2 wrote:

>

format!"fmt"() and writef!"fmt"() templates
with compile-time checked format string
not accept %X for pointers,

but format() and writef() accept it

https://run.dlang.io/is/aQ05Ux

void main() {
    import std.stdio: writefln;
    int x;
    writefln("%X", &x);  //ok
    writefln!"%s"(&x);  //ok
    //writefln!"%X"(&x);  //compile error
}

is this intentional?

Yes. %X is to format integers.

It is to format pointers as well, according to the last table on https://dlang.org/phobos/std_format.html.

Type Format character Formatted as
Pointer 's' A null pointer is formatted as 'null'. All other pointers are formatted as hexadecimal numbers with the format character 'X'.
'x', 'X' Formatted as a hexadecimal number.

It looks like a bug to me.

— Bastiaan.

August 09, 2021
On 8/9/21 3:01 PM, Patrick Schluter wrote:

> On Monday, 9 August 2021 at 19:38:28 UTC, novice2 wrote:
>> format!"fmt"() and writef!"fmt"() templates
>> with compile-time checked format string
>> not accept %X for pointers,
>>
>> but format() and writef() accept it
>>
>> https://run.dlang.io/is/aQ05Ux
>> ```
>> void main() {
>>     import std.stdio: writefln;
>>     int x;
>>     writefln("%X", &x);  //ok
>>     writefln!"%s"(&x);  //ok
>>     //writefln!"%X"(&x);  //compile error
>> }
>> ```
>>
>> is this intentional?
>
> Yes. %X is to format integers. Runtime evaluation of a format string
> does not allow for type checking. When using the template, the
> evaluation can be thorough and the types can be checked properly.

Sensible explanation but it conflicts both with the documentation at

  https://dlang.org/phobos/std_format.html

and the error message for the following:

  // Intentionally wrong specifier:
  writefln!"%_"((int*).init);

Error: expression `FormatException("Expected one of %s, %x or %X for pointer type.", "/usr/include/dmd/phobos/std/format/internal/write.d", 2990LU, null, null, 0u)` is not constant

Both the documentation and the error message suggest %x and %X.

> You
> have 2 solutions for your problem, either a type cast
>
>      writefln!"%X"(cast(size_t)&x);
>
> or using the generic format specifier that will deduce itself the format
> to using depending in the passed type.
>
>      writefln!"%s"(&x);

That would be my choice but I've just learned that %s prints the null value as "null" instead of hex 0, which may be undesirable in some cases.

I think there really is a bug here.

I've been hitting a similar bug with some complex range expressions where compile-time checked format strings would not work. I don't know the reason but I suspect a bug in the compile-time checker that involves .init values for arguments. I assume the checker uses .init values to see whether the format expression compiles and works. In fact, the mention of 'null' in the OP's error message makes me think it may be related. Perhaps the un-typed 'null' literal is used somewhere. (?)

Ali

August 09, 2021
On Monday, 9 August 2021 at 22:30:43 UTC, Ali Çehreli wrote:
> I don't know the reason but I suspect a bug in the compile-time checker that involves .init values for arguments.

The compile time checker is pretty bad tbh, it just tries to ctfe execute the given string and sees if it throws. That's kinda clever; the simplest thing that can possibly work, no doubt. But since ctfe cannot work with certain things - like the pointer casts which are done here* - this makes it a bit fragile. And the implementation is really really slow and pretty bloated in codegen too.

My personal policy is to never use it.

* The compiler probably could special-case `null` at least since that's consistently 0 in D.

> Perhaps the un-typed 'null' literal is used somewhere.

The line is this:

const pnum = () @trusted { return cast(ulong) p; }();


Which is already blargh code, but in ctfe it is a prohibited operation.
August 09, 2021
On 8/9/21 3:46 PM, Adam D Ruppe wrote:

> The compile time checker [...] implementation is really really
> slow and pretty bloated in codegen too.
>
> My personal policy is to never use it.

My personal policy is to kindly ask you to fix it! :p

Ali

August 10, 2021
On Monday, 9 August 2021 at 22:30:43 UTC, Ali Çehreli wrote:
> Error: expression `FormatException("Expected one of %s, %x or %X for pointer type.",

i saw this message too, and this is one of reasons of my original question.

'%s' bad for pointer in my cases, because result often contains something like "init" or "cast(int*)mytype"

i dreamed that programming will be less-error with compile checking format.
but reality disappoint :(
message for every error in compile-checked format occupy whole screen :(

every time i try to use templates, i have problems :(
August 10, 2021

On Tuesday, 10 August 2021 at 05:03:12 UTC, nov wrote:

>

every time i try to use templates, i have problems :(

That is why C++ introduced concepts. Wonder when D will be getting them :(

August 10, 2021
On 8/9/21 10:03 PM, nov wrote:

> i dreamed that programming will be less-error with compile checking format.

I still think so because many errors that can be caught at compile time are moved to run time in non-statically-typed languages.

> but reality disappoint :(
> message for every error in compile-checked format occupy whole screen :(

When that happens, I simply change it to runtime-checked format string like you did and it works. (Better would be to identify and fix the problem. Maybe some other time for me...)

Ali