Thread overview
[Bug 31] New: Keyword 'function' and pointer test broken for IsExpression
Mar 10, 2006
d-bugmail
Mar 15, 2006
Thomas Kuehne
Mar 15, 2006
Sean Kelly
Mar 15, 2006
Thomas Kuehne
Apr 26, 2006
d-bugmail
May 04, 2006
Sean Kelly
May 04, 2006
Sean Kelly
May 05, 2006
Oskar Linde
March 10, 2006
http://d.puremagic.com/bugzilla/show_bug.cgi?id=31

           Summary: Keyword 'function' and pointer test broken for
                    IsExpression
           Product: D
           Version: 0.148
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: walter@digitalmars.com
        ReportedBy: sean@f4.ca


Given the documentation, I would expect all eight tests to pass, yet tests six and eight both fail.


C:\code\d\bugs>type 149_1.d
import std.c.stdio;

template isPointer( T )
{
    const bool isPointer = is( T : T* );
}

void main()
{
    struct S {}
    union U {}
    class C {}
    interface I {}
    enum E { e }
    alias void function() fp;
    alias void delegate() dp;

    static if( is( S == struct ) ) printf( "1. struct passes\n" );
    static if( is( U == union ) ) printf( "2. union passes\n" );
    static if( is( C == class ) ) printf( "3. class passes\n" );
    static if( is( I == interface ) ) printf( "4. interface passes\n" );
    static if( is( E == enum ) ) printf( "5. enum passes\n" );
    static if( is( fp == function ) ) printf( "6. function passes\n" );
    static if( is( dp == delegate ) ) printf( "7. delegate passes\n" );
    static if( isPointer!(int*) ) printf( "8. pointer passes\n" );
}
C:\code\d\bugs>dmd 149_1.d
C:\bin\dmd\bin\..\..\dm\bin\link.exe 149_1,,,user32+kernel32/noi;

C:\code\d\bugs>149_1
1. struct passes
2. union passes
3. class passes
4. interface passes
5. enum passes
7. delegate passes

C:\code\d\bugs>


-- 

March 15, 2006
d-bugmail@puremagic.com schrieb am 2006-03-10:
> Given the documentation, I would expect all eight tests to pass, yet tests six and eight both fail.
>
>
> C:\code\d\bugs>type 149_1.d
> import std.c.stdio;
>
> template isPointer( T )
> {
>     const bool isPointer = is( T : T* );
> }
>
> void main()
> {
>     struct S {}
>     union U {}
>     class C {}
>     interface I {}
>     enum E { e }
>     alias void function() fp;
>     alias void delegate() dp;
>
>     static if( is( S == struct ) ) printf( "1. struct passes\n" );
>     static if( is( U == union ) ) printf( "2. union passes\n" );
>     static if( is( C == class ) ) printf( "3. class passes\n" );
>     static if( is( I == interface ) ) printf( "4. interface passes\n" );
>     static if( is( E == enum ) ) printf( "5. enum passes\n" );
>     static if( is( fp == function ) ) printf( "6. function passes\n" );
>     static if( is( dp == delegate ) ) printf( "7. delegate passes\n" );
>     static if( isPointer!(int*) ) printf( "8. pointer passes\n" );
> }
> C:\code\d\bugs>dmd 149_1.d
> C:\bin\dmd\bin\..\..\dm\bin\link.exe 149_1,,,user32+kernel32/noi;
>
> C:\code\d\bugs>149_1
> 1. struct passes
> 2. union passes
> 3. class passes
> 4. interface passes
> 5. enum passes
> 7. delegate passes

Shouldn't isPointer be defined as:

# template isPointer( T ){
#     const bool isPointer = is( T : void* );
# }

http://www.digitalmars.com/d/expression.html#IsExpression
# is ( Type : TypeSpecialization )
# The condition is satisfied if Type is semantically correct and it is
# the same as or can be implicitly converted to TypeSpecialization.

Thus "is(T : T*)" is always false.

Added to DStress as http://dstress.kuehne.cn/run/i/is_05_A.d http://dstress.kuehne.cn/run/i/is_05_B.d http://dstress.kuehne.cn/run/i/is_05_C.d http://dstress.kuehne.cn/run/i/is_05_D.d http://dstress.kuehne.cn/run/i/is_05_E.d http://dstress.kuehne.cn/run/i/is_05_F.d http://dstress.kuehne.cn/run/i/is_05_G.d http://dstress.kuehne.cn/run/i/is_05_H.d http://dstress.kuehne.cn/run/i/is_06_A.d http://dstress.kuehne.cn/run/i/is_06_B.d http://dstress.kuehne.cn/run/i/is_06_C.d http://dstress.kuehne.cn/run/i/is_06_D.d http://dstress.kuehne.cn/run/i/is_06_E.d http://dstress.kuehne.cn/run/i/is_06_F.d http://dstress.kuehne.cn/run/i/is_06_G.d http://dstress.kuehne.cn/run/i/is_06_H.d http://dstress.kuehne.cn/run/i/is_07_A.d http://dstress.kuehne.cn/run/i/is_07_B.d http://dstress.kuehne.cn/run/i/is_07_C.d http://dstress.kuehne.cn/run/i/is_07_D.d http://dstress.kuehne.cn/run/i/is_07_E.d http://dstress.kuehne.cn/run/i/is_07_F.d http://dstress.kuehne.cn/run/i/is_07_G.d http://dstress.kuehne.cn/run/i/is_07_H.d http://dstress.kuehne.cn/run/i/is_08_A.d http://dstress.kuehne.cn/run/i/is_08_B.d http://dstress.kuehne.cn/run/i/is_08_C.d http://dstress.kuehne.cn/run/i/is_08_D.d http://dstress.kuehne.cn/run/i/is_08_E.d http://dstress.kuehne.cn/run/i/is_08_F.d http://dstress.kuehne.cn/run/i/is_08_G.d http://dstress.kuehne.cn/run/i/is_08_H.d http://dstress.kuehne.cn/run/i/is_09_A.d http://dstress.kuehne.cn/run/i/is_09_B.d http://dstress.kuehne.cn/run/i/is_09_C.d http://dstress.kuehne.cn/run/i/is_09_D.d http://dstress.kuehne.cn/run/i/is_09_E.d http://dstress.kuehne.cn/run/i/is_09_F.d http://dstress.kuehne.cn/run/i/is_09_G.d http://dstress.kuehne.cn/run/i/is_09_H.d http://dstress.kuehne.cn/run/i/is_10_A.d http://dstress.kuehne.cn/run/i/is_10_B.d http://dstress.kuehne.cn/run/i/is_10_C.d http://dstress.kuehne.cn/run/i/is_10_D.d http://dstress.kuehne.cn/run/i/is_10_E.d http://dstress.kuehne.cn/run/i/is_10_F.d http://dstress.kuehne.cn/run/i/is_10_G.d http://dstress.kuehne.cn/run/i/is_10_H.d http://dstress.kuehne.cn/run/i/is_11_A.d http://dstress.kuehne.cn/run/i/is_11_B.d http://dstress.kuehne.cn/run/i/is_11_C.d http://dstress.kuehne.cn/run/i/is_11_D.d http://dstress.kuehne.cn/run/i/is_11_E.d http://dstress.kuehne.cn/run/i/is_11_F.d http://dstress.kuehne.cn/run/i/is_11_G.d http://dstress.kuehne.cn/run/i/is_11_H.d http://dstress.kuehne.cn/run/i/is_12_A.d http://dstress.kuehne.cn/run/i/is_12_B.d http://dstress.kuehne.cn/run/i/is_12_C.d http://dstress.kuehne.cn/run/i/is_12_D.d http://dstress.kuehne.cn/run/i/is_12_E.d http://dstress.kuehne.cn/run/i/is_12_F.d http://dstress.kuehne.cn/run/i/is_12_G.d http://dstress.kuehne.cn/run/i/is_12_H.d

Thomas


March 15, 2006
Thomas Kuehne wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> d-bugmail@puremagic.com schrieb am 2006-03-10:
>> Given the documentation, I would expect all eight tests to pass, yet tests six
>> and eight both fail.
>>
>>
>> C:\code\d\bugs>type 149_1.d
>> import std.c.stdio;
>>
>> template isPointer( T )
>> {
>>     const bool isPointer = is( T : T* );
>> }
>>
>> void main()
>> {
>>     struct S {}
>>     union U {}
>>     class C {}
>>     interface I {}
>>     enum E { e }
>>     alias void function() fp;
>>     alias void delegate() dp;
>>
>>     static if( is( S == struct ) ) printf( "1. struct passes\n" );
>>     static if( is( U == union ) ) printf( "2. union passes\n" );
>>     static if( is( C == class ) ) printf( "3. class passes\n" );
>>     static if( is( I == interface ) ) printf( "4. interface passes\n" );
>>     static if( is( E == enum ) ) printf( "5. enum passes\n" );
>>     static if( is( fp == function ) ) printf( "6. function passes\n" );
>>     static if( is( dp == delegate ) ) printf( "7. delegate passes\n" );
>>     static if( isPointer!(int*) ) printf( "8. pointer passes\n" );
>> }
>> C:\code\d\bugs>dmd 149_1.d
>> C:\bin\dmd\bin\..\..\dm\bin\link.exe 149_1,,,user32+kernel32/noi;
>>
>> C:\code\d\bugs>149_1
>> 1. struct passes
>> 2. union passes
>> 3. class passes
>> 4. interface passes
>> 5. enum passes
>> 7. delegate passes
> 
> Shouldn't isPointer be defined as:
> 
> # template isPointer( T ){
> #     const bool isPointer = is( T : void* );
> # }
> 
> http://www.digitalmars.com/d/expression.html#IsExpression
> # is ( Type : TypeSpecialization )
> # The condition is satisfied if Type is semantically correct and it is
> # the same as or can be implicitly converted to TypeSpecialization.
> 
> Thus "is(T : T*)" is always false.

Good point.  However, this is inconsistent with the template specialization syntax, where "template foo( T : T* )" is completely valid.  But perhaps that doesn't matter as IsExpression differs in other ways as well.  I suppose that leaves 'function' then.

By the way, this code:

    class C { void fn() {} }
    static if( is( typeof(C.fn) == function ) )
        pragma( msg, "is function\n" );
    static if( is( typeof(C.fn) == delegate ) )
        pragma( msg, "is delegate\n" );


prints "is function" if compiled.  Aren't non-static class functions actually delegates?


Sean
March 15, 2006
Sean Kelly schrieb am 2006-03-15:
> By the way, this code:
>
>      class C { void fn() {} }
>      static if( is( typeof(C.fn) == function ) )
>          pragma( msg, "is function\n" );
>      static if( is( typeof(C.fn) == delegate ) )
>          pragma( msg, "is delegate\n" );
>
>
> prints "is function" if compiled.  Aren't non-static class functions actually delegates?

Added to DStress as http://dstress.kuehne.cn/run/i/is_13_A.d http://dstress.kuehne.cn/run/i/is_13_B.d http://dstress.kuehne.cn/run/i/is_13_C.d http://dstress.kuehne.cn/run/i/is_13_D.d

Thomas


April 26, 2006
http://d.puremagic.com/bugzilla/show_bug.cgi?id=31


bugzilla@digitalmars.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |INVALID




------- Comment #4 from bugzilla@digitalmars.com  2006-04-26 13:43 -------
>alias void function() fp;
>static if( is( fp == function ) ) printf( "6. function passes\n" );

fp is not declared as a function, it is declared as a pointer to a function. If
fp is declared as:
    alias void fp();
it will 'pass'.

>template isPointer( T )
>{
>    const bool isPointer = is( T : T* );
>}
>static if( isPointer!(int*) ) printf( "8. pointer passes\n" );

Here, int* is passed as T to isPointer. The is(T:T*) is evaluated as
is(int*:int**), and so it fails. To detect a pointer, use is(T:void*).

>class C { void fn() {} }
>     static if( is( typeof(C.fn) == function ) )
>         pragma( msg, "is function\n" );
>     static if( is( typeof(C.fn) == delegate ) )
>         pragma( msg, "is delegate\n" );
>prints "is function" if compiled.  Aren't non-static class functions actually delegates?

No. Class functions are functions. A delegate is a pointer to a class function.


-- 

May 04, 2006
d-bugmail@puremagic.com wrote:
>>
>> alias void function() fp;
>> static if( is( fp == function ) ) printf( "6. function passes\n" );
> 
> fp is not declared as a function, it is declared as a pointer to a function. If
> fp is declared as:
>     alias void fp();
> it will 'pass'.

So how do I test if T is a function pointer?  Currently, I can test if T is a delegate via "if( is(T==delegate) )" but "if( is(T==function) )" clearly has a different meaning.  For example:

    void delegate() dp;

    template isDelegate( T )
    {
        const bool isDelegate = is( T == delegate );
    }

    static assert( isDelegate!(dp) );

So far so good, but:

    void function() fp;

    template isFunctionPointer( T )
    {
        const bool isFunctionPointer = ???;
    }

    static assert( isFunctionPointer!(fp) );

Currently, I'm examining the mangled name, which is a terrible hack:

    template isFunctionPointer( T )
    {
        const bool isFunctionPointer= T.mangleof.length > 2 &&
                                      T.mangleof[0] == 'P'  &&
                                      T.mangleof[1] == 'F';
    }



Sean
May 04, 2006
Sean Kelly wrote:
> 
> So how do I test if T is a function pointer?

By the way.  If you're planning to eventually merge function pointers into delegates then I suppose there's no point in adding language support for this (assuming something doesn't already exist that I'm simply missing).  I'd be content to use the workaround until then.


Sean
May 05, 2006
Sean Kelly wrote:
> d-bugmail@puremagic.com wrote:
>>>
>>> alias void function() fp;
>>> static if( is( fp == function ) ) printf( "6. function passes\n" );
>>
>> fp is not declared as a function, it is declared as a pointer to a function. If
>> fp is declared as:
>>     alias void fp();
>> it will 'pass'.
> 
> So how do I test if T is a function pointer?  Currently, I can test if T is a delegate via "if( is(T==delegate) )" but "if( is(T==function) )" clearly has a different meaning.  For example:
> 
>     void delegate() dp;
> 
>     template isDelegate( T )
>     {
>         const bool isDelegate = is( T == delegate );
>     }
> 
>     static assert( isDelegate!(dp) );

I assume you mean isDelegate!(typeof(dp)).

> 
> So far so good, but:
> 
>     void function() fp;
> 
>     template isFunctionPointer( T )
>     {
>         const bool isFunctionPointer = ???;
>     }
> 
>     static assert( isFunctionPointer!(fp) );

Try:

template declare(T) { T declare; }

template isFunctionPointer(T) {
  const bool isFunctionPointer = is( typeof(*declare!(T)) == function);
}

/Oskar