Thread overview
__traits(compileError, {})
Sep 08, 2017
bitwise
Sep 10, 2017
bitwise
Sep 11, 2017
Jonathan M Davis
Sep 11, 2017
bitwise
Sep 11, 2017
Jonathan M Davis
Sep 11, 2017
Timon Gehr
Sep 11, 2017
bitwise
September 08, 2017
Lately, I've been hit by several compilation errors when phobos fails to construct an instance of a class or struct I've pass it. Regardless of what the exact failure is, phobos usually gives you some generic error that isn't helpful.

Example:

class Test {
    @disable this();
}

int main(string[] argv) {
    auto sz = __traits(classInstanceSize, Test);
    auto mem = malloc(sz)[0..sz];
    emplace!Test(mem);
    return 0;
}

The above code fails with this error:

'Error: static assert  "Don't know how to initialize an object of type Test with arguments ()"'

@disable'd constructors are only one of the reasons I've hit this snag.
Once though, I was having an extremely hard time figuring out what was wrong, and the fix was simply to modify emplace(). I removed the line below from emplace(), and forced the constructor call, which led to a much more helpful error.

`// static if (is(typeof(result.__ctor(args1))))`

If you simply did that though, it may not be obvious to everyone what happened, but if you had __traits(compilerError, {}) then you could dress the error up as appropriate:

"Emplace failed with error:\n\t'" ~ __traits(compileError, { result.__ctor(args1) }) ~ "."

The alternative would be to manually code redundant error checks that the compiler already does into everything in phobos that needs to construct objects, which seems much worse than implementing something like __traits(compileError, {}).

Thoughts?

September 10, 2017
On Friday, 8 September 2017 at 01:18:46 UTC, bitwise wrote:
> Lately, I've been hit by several compilation errors when phobos fails to construct an instance of a class or struct I've pass it. Regardless of what the exact failure is, phobos usually gives you some generic error that isn't helpful.
>
> [...]

Does anyone even follow procedures of any kind for additions this trivial, or do they just do pull requests and debate it there?
September 11, 2017
On Sunday, September 10, 2017 23:25:59 bitwise via Digitalmars-d wrote:
> On Friday, 8 September 2017 at 01:18:46 UTC, bitwise wrote:
> > Lately, I've been hit by several compilation errors when phobos fails to construct an instance of a class or struct I've pass it. Regardless of what the exact failure is, phobos usually gives you some generic error that isn't helpful.
> >
> > [...]
>
> Does anyone even follow procedures of any kind for additions this trivial, or do they just do pull requests and debate it there?

Additions to the standard library on the size of new modules or redesigned modules require a formal review in the main newsgroup, but making changes to individual functions don't. If you're looking to add something to the compiler, it could simply be a PR, or it could require a DIP, depending on its scope and what Walter and the other compiler devs think.

In the case of your suggestion, I'd argue that it would simply be better to improve the compiler-generated error messages if they're not good enough rather than trying to add some mechanism to inject messages from the programmer into the compiler's error messages. And remember that you do already have static assert, pragma(msg, ...), and __traits(compiles, ...) to work with if you want to be adding additional compile-time checks and/or printing out additional messages at compile time.  But if you have an idea that you want to implement and try and get in, then implement it and create a PR. Worst case, they tell you that it's not a desirable change or that a more formal review is necessary. And in the latter case, that just means that you then know what you need to do to go to the next step.

- Jonathan M Davis

September 11, 2017
On Monday, 11 September 2017 at 00:15:08 UTC, Jonathan M Davis wrote:
> On Sunday, September 10, 2017 23:25:59 bitwise via Digitalmars-d wrote:
>> On Friday, 8 September 2017 at 01:18:46 UTC, bitwise wrote:
>> > [...]
>>
>> Does anyone even follow procedures of any kind for additions this trivial, or do they just do pull requests and debate it there?
>
> Additions to the standard library on the size of new modules or redesigned modules require a formal review in the main newsgroup, but making changes to individual functions don't. If you're looking to add something to the compiler, it could simply be a PR, or it could require a DIP, depending on its scope and what Walter and the other compiler devs think.

Ok, makes sense - Thanks. My own learning curve aside though, it doesn't seem prohibitively time consuming to just try this myself at some point.

> In the case of your suggestion, I'd argue that it would simply be better to improve the compiler-generated error messages if they're not good enough.

I'm suggesting the opposite. I'm saying that the compiler messages _are_ good enough, but that some functions in phobos (emplace, for example) suppress them by using code like this:

`
static if(__traits(compiles, { ... }))
    doIt();
else
    static assert("custom error message");
`

So instead of a custom error message, you could simply run the offending code through the compiler and output what it says. The compiler's error message would most likely be much better and more detailed than the custom one inserted by hand.

So essentially, the above would be refactored like this:

`
static if(__traits(compiles, { doIt(); }))
    doIt();
else
    static assert("Failed to invoke 'doIt': \n\t" ~ __traits(compilerError, { doIt(); }));
`

For the case of emplace() though, I'm wondering if that static if even needs to be there at all - maybe not.

September 11, 2017
On Monday, September 11, 2017 00:41:12 bitwise via Digitalmars-d wrote:
> On Monday, 11 September 2017 at 00:15:08 UTC, Jonathan M Davis
> > In the case of your suggestion, I'd argue that it would simply be better to improve the compiler-generated error messages if they're not good enough.
>
> I'm suggesting the opposite. I'm saying that the compiler messages _are_ good enough, but that some functions in phobos (emplace, for example) suppress them by using code like this:
>
> `
> static if(__traits(compiles, { ... }))
>      doIt();
> else
>      static assert("custom error message");
> `
>
> So instead of a custom error message, you could simply run the offending code through the compiler and output what it says. The compiler's error message would most likely be much better and more detailed than the custom one inserted by hand.
>
> So essentially, the above would be refactored like this:
>
> `
> static if(__traits(compiles, { doIt(); }))
>      doIt();
> else
>      static assert("Failed to invoke 'doIt': \n\t" ~
> __traits(compilerError, { doIt(); }));
> `
>
> For the case of emplace() though, I'm wondering if that static if even needs to be there at all - maybe not.

Well, if you find anything in a Phobos function that you think is suboptimal, feel free to create a PR to fix it.

- Jonathan M Davis

September 11, 2017
On 08.09.2017 03:18, bitwise wrote:
> Lately, I've been hit by several compilation errors when phobos fails to construct an instance of a class or struct I've pass it. Regardless of what the exact failure is, phobos usually gives you some generic error that isn't helpful.
> 
> Example:
> 
> class Test {
>      @disable this();
> }
> 
> int main(string[] argv) {
>      auto sz = __traits(classInstanceSize, Test);
>      auto mem = malloc(sz)[0..sz];
>      emplace!Test(mem);
>      return 0;
> }
> 
> The above code fails with this error:
> 
> 'Error: static assert  "Don't know how to initialize an object of type Test with arguments ()"'
> 
> @disable'd constructors are only one of the reasons I've hit this snag.
> Once though, I was having an extremely hard time figuring out what was wrong, and the fix was simply to modify emplace(). I removed the line below from emplace(), and forced the constructor call, which led to a much more helpful error.
> 
> `// static if (is(typeof(result.__ctor(args1))))`
> 
> If you simply did that though, it may not be obvious to everyone what happened, but if you had __traits(compilerError, {}) then you could dress the error up as appropriate:
> 
> "Emplace failed with error:\n\t'" ~ __traits(compileError, { result.__ctor(args1) }) ~ "."
> 
> The alternative would be to manually code redundant error checks that the compiler already does into everything in phobos that needs to construct objects, which seems much worse than implementing something like __traits(compileError, {}).
> 
> Thoughts?

The dangerous thing about this suggestion is that it makes the compilation errors DMD implements de facto part of the semantics of the D language. I.e. improving compiler diagnostics becomes a breaking language change.
September 11, 2017
On Monday, 11 September 2017 at 11:07:46 UTC, Timon Gehr wrote:
>
> The dangerous thing about this suggestion is that it makes the compilation errors DMD implements de facto part of the semantics of the D language. I.e. improving compiler diagnostics becomes a breaking language change.

I guess this is true if people start trying to parse the error messages to extract details, but shouldn't there be some level of standardization for tools anyways?


Thinking about this a little further though, I think the behavior I had in mind could be implemented without changes.

My example from above could become this:

`
static if(!__traits(compiles, { doIt(); }))
{
    // now, we know it's about to fail
    pragma(msg, "doIt() failed because....");
}

// do it anyways and let the compiler output it's regular error message
doIt();
`