__traits(compiles, ...) returns true for syntactic garbage and for semantically incorrect code

Pavel proger79 at gmail.com
Mon Dec 17 04:20:22 PST 2012


On Monday, 17 December 2012 at 12:04:30 UTC, Pavel wrote:
> On Monday, 17 December 2012 at 11:03:01 UTC, Simen Kjaeraas 
> wrote:
>> On 2012-42-17 11:12, Pavel <proger79 at gmail.com> wrote:
>>
>>> Either I do not understand the work of this feature or it is 
>>> an obvious bug:
>>>
>>> import std.stdio;
>>> import std.conv;
>>>
>>> void main()
>>> {
>>>   enum string expr = "DMD compiles this garbage ... iiiii - 
>>> \" #### $$$";
>>> 	
>>>   enum bool bTest = __traits(compiles, expr);
>>>   enum bool bTest2 = __traits(compiles, "int i = q{};");
>>> 		
>>>   writeln("bTest: " ~ to!string(bTest));
>>>   writeln("bTest2: " ~ to!string(bTest2));
>>> }
>>>
>>> Produces (tested with dmd32 2.060 and dmd32 2.059):
>>>  bTest: true
>>>  bTest2: true
>>>
>>> (http://dpaste.dzfl.pl/5d338ab3)
>>>
>>> Could you please somebody explain this?
>>>
>>> Thanks,
>>> Pavel
>>
>> Let's start off with the obligatory 'You're doing it wrong'.
>>
>> __traits(compiles, ...) does not check the content of strings.
>> If you want that, use mixin("somestring").
>>
>> What your code does is simply check if the string is one that
>> could be embedded in D code, which both of them can.
>>
>> If instead of using strings you do this:
>>
>>   enum bool bTest2 = __traits(compiles, {int i = q{};});
>>
>> You will see that the result is false.
>
>
> Nice hint with __traits(compiles, { <statements> }) - thanks!
> (Because as I've now read in documentation the 
> __traits(compiles) does not accepts statements directly.)
>
> Because when writing templates with operating code as strings 
> it is easy to forget that __traits(compiles, ...) behaves so I 
> suppose it is useful to create a utility template for it:
>
> template Compiles(string code)
> {
>    enum bool Compiles = __traits(compiles, mixin("{" ~ code ~ 
> "}"));
> }
>
> void main()
> {
>    enum string code1 = "int i = q{};";
>    enum string code2 = "int i = 5; i++;";
> 	
>    writeln("Compiles `" ~ code1 ~ "`: " ~ 
> to!string(Compiles!code1));
>    writeln("Compiles `" ~ code2 ~ "`: " ~ 
> to!string(Compiles!code2));
> }

Oops, bad idea - it will work only for self-contained code but 
will not work when code references some variables from current 
scope.


More information about the Digitalmars-d mailing list