Thread overview
Limitations of __traits(compiles, {})
Jul 23, 2020
Per Nordlöw
Jul 23, 2020
Adam D. Ruppe
Jul 23, 2020
Per Nordlöw
July 23, 2020
Why doesn't

    static assert(!__traits(compiles, {
        void f() { int[2] _ = [1, 2]; foreach (const auto ref e; _) {} }
    }));

compile when

    static assert(__traits(compiles, {
        void f() { int[2] _ = [1, 2]; foreach (const ref e; _) {} }
    }));

does?

Doesn't __traits(compiles) support syntactic changes to the language that hasn't yet been implemented?

If so, is there some other way of detecting this?

I want these to automatically detect and signal with a failing `static assert` when a new language feature has been implemented or preview-activated so it can be used.

For comparison see

/** Is `true` iff DIP-1000 checking is enabled via compiler flag -dip1000.
 *
 * See_Also: https://forum.dlang.org/post/qglynupcootocnnnpmhj@forum.dlang.org
 * See_Also: https://forum.dlang.org/post/pzddsrwhfvcopfaamvak@forum.dlang.org
 */
enum isDIP1000 = __traits(compiles, () @safe { int x; int* p; p = &x; });

which can be used to optionally static tests using __traits(compiles) when -dip1000 has been fed to the compiler.
July 23, 2020
On Thursday, 23 July 2020 at 13:33:02 UTC, Per Nordlöw wrote:
> Doesn't __traits(compiles) support syntactic changes to the language that hasn't yet been implemented?

The whole codebase must pass the parser before it even considers what is in there. So new syntax cannot be detected through this or version or anything else.... unless the code is quoted.

If the code is in quotes - as a string - then the parser doesn't look at it until it needs to. So you might be able to detect using mixin.

__traits(compiles, mixin(" your code here"))

July 23, 2020
On Thursday, 23 July 2020 at 13:59:39 UTC, Adam D. Ruppe wrote:
> If the code is in quotes - as a string - then the parser doesn't look at it until it needs to. So you might be able to detect using mixin.
>
> __traits(compiles, mixin(" your code here"))

Thanks.

Solved via mixins as:


@safe pure nothrow @nogc:

private enum hasAutoRefForeach = __traits(compiles, () {
        mixin(`void f() { int[2] _ = [1, 2]; foreach (const auto ref e; _) {} }`);
    });

private enum hasRefForeach = __traits(compiles, {
        mixin(`void f() { int[2] _ = [1, 2]; foreach (const ref e; _) {} }`);
    });

///
unittest
{
    static assert(hasRefForeach);
    static assert(!hasAutoRefForeach);
}