Solving a constraint hiding an error in a function literal

Steven Schveighoffer schveiguy at gmail.com
Fri Feb 3 20:20:48 UTC 2023


On 2/3/23 1:55 PM, Paul Backus wrote:
> On Friday, 3 February 2023 at 12:43:54 UTC, Nick Treleaven wrote:
>> Initially I thought a constraint expression like `__traits(compiles, 
>> a())` should be moved to a `static if` test with a helpful error 
>> message. std.algorithm.all was changed to use static assert instead:
>>
>> https://issues.dlang.org/show_bug.cgi?id=13683
>> https://github.com/dlang/phobos/pull/6607/files
>>
>> But that still swallows the actual compile error and just says the 
>> callable doesn't work without really saying why (why isn't it a unary 
>> predicate if it accepts `range.front` as an argument?). Alternatively, 
>> the constraint check could be removed and you will get an internal 
>> error actually stating the precise error in the callable's body. But 
>> it doesn't help with overloading (see below).
>>
>> What if there was a new trait to solve this? Suppose 
>> `__traits(callable, expr, args)`, that just does IFTI (if `expr` is a 
>> function template) and then checks that the parameter list of `expr` 
>> accepts `args`. It does not check that `expr(args)` actually compiles, 
>> it ignores any errors in the body of `expr`.
> 
> I think a better solution would be to have `__traits(compiles)` return 
> the error message(s) when it fails, instead of just a boolean `false`. 
> Then we could write code like:
> 
> ```d
> enum compResult = __traits(compiles, expr);
> static if (compResult) // implicitly converts to bool
> {
>      doStuffWith(expr);
> }
> else
> {
>      // print error message
>      static assert(0, compResult.message);
> }
> ```
> 
> Getting constraints to understand this would require compiler changes, 
> but that shouldn't be *too* difficult. Might also be worth having 
> `static assert(__traits(compiles, expr))`, without an explicit message 
> argument, print the returned message.

The problem with this is that your constraint then has to become:

```d
foo(alias bar) if (__traits(compiles, 
exprUsingBar).hasOnlyImplementationIssues)
```
That `hasOnlyImplementationIssues` is going to be messy, difficult to 
implement, and basically redoing all that the compiler is already doing. 
Plus, if it's just a string, it might have to change with compiler 
versions. Essentially, changing error messages becomes a breaking change.

-Steve


More information about the Digitalmars-d mailing list