idea: static scope(failure)

max haughton maxhaton at gmail.com
Wed Apr 20 01:07:30 UTC 2022


On Wednesday, 26 January 2022 at 01:58:23 UTC, Steven 
Schveighoffer wrote:
> Just recently running into some problems where deeply nested 
> inside some library code, a static assert triggers. Of course, 
> the static assert doesn't give any context with which it was 
> called from *my* code.
>
> And the compiler helpfully says something like (names changed 
> to protect the proprietary):
>
> ```
> somelibrary.d(263,16):        instantiated from here: 
> `foo!(Json[string])`
> somelibrary.d(286,25):        instantiated from here: 
> `bar!(Json[string])`
> somelibrary.d(204,16):        instantiated from here: 
> `baz!(Json)`
> somelibrary.d(263,16):        ... (1 instantiations, -v to 
> show) ...
> ```
>
> OK, so it stopped telling me useful information. And on top of 
> that, the information isn't always enough to determine the 
> cause, because in one of these instantiations, there's probably 
> a static foreach, where I don't know which element being looped 
> over is actually the cause.
>
> If this was runtime I'd do something like:
>
> ```d
> scope(failure) writeln("Context: ", relevant, info);
> ```
>
> And then when the exception is thrown, I can see some context. 
> But I can't do that at compile time.
>
> What I've done instead is:
>
> ```d
> static if(!__traits(compiles, entireLineOfCode)) pragma(msg, 
> "Context: ", relevant, info);
> entireLineOfCode;
> ```
>
> Which is *OK*, but the place where I might want to print the 
> context might not be for just one line of code, you might have 
> to repeat an entire mess of stuff. And I was thinking, wouldn't 
> it be cool to just do something like:
>
> ```d
> static scope(failure) pragma(msg, stuff);
> ```
>
> Then, no matter what the context, or where it's failing, I can 
> ensure that on a failure to compile, I can tease out some debug 
> info at the relevant spot.
>
> another possible syntax is something like:
>
> ```d
> pragma(msgOnFailure, stuff);
> ```
>
> Which might even be gagged if the compiler isn't actually 
> failing (i.e. this is inside a `__traits(compiles)`)
>
> Does this (or something like it) make sense?
>
> -Steve

As steve and I have been discussing on the D discord, I've 
implemented this locally and had a play with it.

```d
void main()
{
     string x;
     int y;
     set(x, y);
}

void set(T...)(ref T x)
{
     foreach(idx, elem; x)
     {
         elem = "a string";
         static scope(failure)
             static assert(0, "I couldn't set tuple[" ~ 
idx.stringof ~ "] equal to \"string\"");
     }
}
```

works with basically 10 lines of code added to the compiler.



More information about the Digitalmars-d mailing list