Difference between "can call" and "can compile"

Paul Backus snarwin at gmail.com
Mon Sep 7 16:12:02 UTC 2020


On Monday, 7 September 2020 at 14:57:24 UTC, Steven Schveighoffer 
wrote:
> I get a compilation error. But it's not in foo, it's in bar. It 
> says:
>
> Error: template instance onlineapp.bar!(foo) does not match 
> template declaration bar(alias x)()
>   with x = foo(T)(T v)
>   must satisfy the following constraint:
>        __traits(compiles, x(1))
>
> [...]
>
> The problem is, if the intention is for it to pass, but the 
> implementation is bugged, the error message is useless. If the 
> thing I'm passing is a type with 200 LOC, and there's an error 
> buried in there somewhere, the compiler is telling me 
> "somewhere in this, it doesn't work". And sometimes those 
> function signatures and their constraints are hairy themselves.
>
> My usual steps taken at this point are to extract the 
> constraint template and actually try to call the functions in 
> the constraints with that type, and see what fails. This is 
> somewhat annoying, and sometimes difficult to do based on where 
> the code that implements the constraint actually is, and where 
> the code actually calling it is (I may have to duplicate a lot 
> of stuff).

The tedious-but-reliable way to handle this is to recompile with 
`-verrors=spec`, search the output for the original error 
message, and then scroll up until you find what you're looking 
for in the speculative errors. The only issue is that you have to 
wade through a lot of useless chaff to find the information you 
actually care about.

IMO the best way to make this easier would be to have the 
compiler provide a "stack trace" of speculative errors for each 
failed constraint whenever a template fails to instantiate--maybe 
behind a switch (`-verrors=constraints`) to avoid clogging up the 
output in the common case.

This has the advantage of working for *all* indirect errors like 
this, not just ones involving IFTI. To give a concrete example, 
`-verrors=constraints` would have helped me a lot with the 
problems I had to debug in SumType's copy constructors recently 
[1], whereas __traits(canCall) would have been completely useless.

[1] https://github.com/pbackus/sumtype/issues/36


More information about the Digitalmars-d mailing list