__traits(compiles, ...) with syntax errors

Jonathan M Davis newsgroup.d at jmdavisprog.com
Mon Jan 14 23:31:06 UTC 2019


On Monday, January 14, 2019 2:57:28 PM MST Paul Backus via Digitalmars-d 
wrote:
> On Monday, 14 January 2019 at 21:47:40 UTC, Steven Schveighoffer
>
> wrote:
> > How many times have you written something like:
> >
> > void foo(T)(T t) if (__traits(compiles, t.bar())) // or
> > is(typeof(t.bar()))
> > {
> >
> >    t.bar();
> >
> > }
> >
> > And somehow, somewhere, this isn't called? Then you remove the
> > constraint, and find that there's a syntax error in the bar
> > template function (like a missing semicolon).
>
> Ideally, you would catch this in the unit tests for `bar`. You
> are writing unit tests, aren't you? ;)

Good unit tests catch a lot, but it's hard for them to catch everything, and
having to test for stuff that the compiler can trivially tell you can get
really annoying. That's not to say that the compiler should find everything
for you, but sometimes, having it be able to tell you a bit more than
currently it does could save a lot of trouble. In this particular case, it's
not uncommon to have alternate implementations depending on compile time
conditionals. e.g. stuff like

static if(isRandomAccessRange!R)
{
    ...
}
else
{
    ...
}

isn't all that uncommon in optimized range code. The function may work just
fine whether the range is random-access or not, but the actual code that
gets compiled in (and therefore its performance) could vary quite a bit
depending on the range's capabilities.

Syntax errors are less likely in code like that than code that uses is
expressions or __traits(compiles, ...) directly, but the problem that Steven
brings up is very real - and in a way that it can actually be rather
difficult to test for. In many cases, you're basically forced to put in
pragmas or invalid code to see which branches are being compiled. Having a
trait similar to __traits(compiles, ...) but which actually gives you an
error for syntax errors would catch _some_ of the problems surrounding
branching on compile-time conditionals. However, given that it's still not
verifying that the correct branch was taken (just that the test is
syntactically valid), it still wouldn't solve the entire problem. It would
catch a certain class of bugs though. And they're bugs that wouldn't exist
anywhere outside of an is expression or __traits(compiles), ...), because
everywhere else, such syntax errors would be caught. It's just that with
those constructs, those errors basically get shut up and treated simply as
false (which is probably the wrong behavior in all cases except perhaps for
those that involve checking code that's been mixed in).

- Jonathan M Davis





More information about the Digitalmars-d mailing list