std.format and uninitialized elements in CTFE

berni44 dlang at d-ecke.de
Sun Dec 8 19:41:48 UTC 2019


On Sunday, 8 December 2019 at 18:16:29 UTC, Steven Schveighoffer 
wrote:
>> Ali's example shows, that this is a serious issue. IMHO my 
>> example should print `Foo(void)` or `Foo([void, void, void])` 
>> with `int[3]`. With that, Ali's example will work.
>
> Ali's example is different, because it's given an *actually 
> initialized* structure, not one that is uninitialized, and the 
> compiler complains. I'd consider that an actual bug (in Phobos 
> I would guess, not the compiler).

Well actually format uses only the *type* S of the second 
parameter and uses S.init to check if that can be printed (if it 
would use the real parameter, that could have unwanted side 
effects I guess). It cannot print it, because S.init contains an 
uninitialized member. This produces the error "cannot read 
uninitialized variable i in CTFE". So, at that time, the code is 
somehow able to recognize, that the variable "i" is 
uninitialized, else it could not produce this error. What I'm 
looking for is a way, to catch that. That would solve the issue.

> You are thinking incorrectly about CTFE ;) It's executing an 
> *already compiled* function, at compile time.

That's indeed something, I did not know. :-)

> It's hard to have discussions about abstract types that 
> obviously are not useful. Maybe if you have a more likely 
> example, you can get help finding the right course of action.

As I wrote above, I was looking into issue 19769. This is the 
test given there:

```
import std.uni;
import std.format;
static immutable x = format("%s", 
cast(const)"test".asCapitalized);
```

This doesn't compile, because asCapitalized returns a struct 
(ToCapitalizerImpl), which contains uninitialized data (dchar[3] 
buf = void;) and format tries to print that. It first tries to 
print it as a range, but isInputRange misses somehow, that this 
struct is a range (probably because of the cast(const), but I 
don't know exactly) and therefore formatValueImpl tries to print 
the members of that struct directly, but as buf is not 
initialized, that fails. And the result is a strange error 
message (about uninitialized variables, where everything looks 
initialized).

This bug could be fixed by making isInputRange recognize the 
struct as a range. But while I looked, what happens, I found out, 
that printing structs with uninitialized data fails (but with an 
errormessage, that says, that this data is uninitialized). I 
thought, it would be nice, if format would just print <void> 
instead of throwing an error and hence my question if doing so is 
possible.


More information about the Digitalmars-d mailing list