Thread overview
[Issue 11124] New: support "is (T : struct)" syntax
Sep 25, 2013
Kenji Hara
Sep 25, 2013
Andrej Mitrovic
Sep 25, 2013
Kenji Hara
September 25, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11124

           Summary: support "is (T : struct)" syntax
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: monarchdodra@gmail.com


--- Comment #0 from monarchdodra@gmail.com 2013-09-25 07:19:57 PDT ---
As well as:
is (T : class)
is (T : interface)
is (T : union)

This could be useful in two scenarios:

The case where T represents a enum instance of said type. For example:
struct T {}
enum E : T {a = T.init}

In this case, E being an enum, it isn't a struct, however, it would be useful
to know if it can "decay" to a struct type. This syntax would make proper enum
handling correct "by default" rather than explicitly, EG:
is (T : struct)
vs
is (OriginalType!T == struct)

This (I think), is actually quite important, as it increases the chances of code being correct with no special extra content, as well as lower the overall complexity.



Another case where this could be useful, is if T defines an alias this that resolves to another type:

class C
{
    T t;
    alias t this;
}

is (T == struct); //false
is (T : struct); //true

Related conversation: http://forum.dlang.org/thread/vmfiodpnsuzmxrogdxjg@forum.dlang.org

Also, as a general rule, it's more consistent. If:
is (T : U);

is legal, then so should:
is (T : struct);

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 25, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11124



--- Comment #1 from monarchdodra@gmail.com 2013-09-25 08:55:45 PDT ---
Also, use case that we might want to support (but I'm not 100% sure on this):

is (typeof(f) : delegate)

idea being that a function is also a delegate (?) Not entirely sure this is actually true though. Still, a struct might be implicitly castable via alias this to a delegate, so ": delegate" and ": function" would be useful.

See also: http://d.puremagic.com/issues/show_bug.cgi?id=11123

This might have been avoided with useage of ": delegate" as opposed to "== delegate"

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 25, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11124



--- Comment #2 from Kenji Hara <k.hara.pg@gmail.com> 2013-09-25 09:06:36 PDT ---
(In reply to comment #0)
> Another case where this could be useful, is if T defines an alias this that resolves to another type:
> 
> class C
> {
>     T t;
>     alias t this;
> }
> 
> is (T == struct); //false
> is (T : struct); //true

Mistake of:

is (C == struct); //false
is (C : struct); //true

?

And, how this will work when multiple alias this is properly implemented?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 25, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11124


Andrej Mitrovic <andrej.mitrovich@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrej.mitrovich@gmail.com


--- Comment #3 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-09-25 09:24:35 PDT ---
(In reply to comment #2)
> And, how this will work when multiple alias this is properly implemented?

I think we should think about adding a new 'is' expression for alias this checks, because I've already ran into an issue with them interfering with the is(T : X) syntax. I'm thinking we could introduce something like the following:

if (is(T : alias X)) => T has a subtype of type X

I can't find my other bug report right now where I mention this, I'll look into it later.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 25, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11124



--- Comment #4 from monarchdodra@gmail.com 2013-09-25 09:53:24 PDT ---
(In reply to comment #2)
> And, how this will work when multiple alias this is properly implemented?

I don't understand the problem? Isn't it the same as, say: "is (C : int)"?

I don't see what is so special about struct:

class C
{
    T t;
    int i;
    alias t this;
    alias i this;
}
is (C == struct); //false
is (C == int); //false
is (C : struct); //true
is (C : int); //true

Or am I missing something obvious? Apologies in advance.

> I've already ran into an issue with them interfering with the
is(T : X) syntax

Isn't the point that they *do* interfere with such syntax?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 25, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11124



--- Comment #5 from monarchdodra@gmail.com 2013-09-25 09:59:46 PDT ---
(In reply to comment #2)
> (In reply to comment #0)
> > Another case where this could be useful, is if T defines an alias this that resolves to another type:
> > 
> > class C
> > {
> >     T t;
> >     alias t this;
> > }
> > 
> > is (T == struct); //false
> > is (T : struct); //true
> 
> Mistake of:
> 
> is (C == struct); //false
> is (C : struct); //true
> 
> ?

Yes. Sorry. Your code is correct.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 25, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11124



--- Comment #6 from Kenji Hara <k.hara.pg@gmail.com> 2013-09-25 10:33:27 PDT ---
(In reply to comment #4)
> (In reply to comment #2)
> > And, how this will work when multiple alias this is properly implemented?
> 
> I don't understand the problem? Isn't it the same as, say: "is (C : int)"?

Today,
1. is(T U == super) captures the super class list of T in U.

  class C : Object {}
  static if (is(C U == super)) { static assert(is(U[0] == Object)); }

2. If T is implicitly convertible to U, is(T X : U) captures T in X.

Then, if multiple alias this is supported:

  struct S1 {}
  struct S2 {}
  struct S {
    S1 s1;  alias s1 this;
    S2 s2;  alias s2 this;
  }
  static if (is(S U : struct)) { /* What's captured in U? */ }

Based on the #1, U would capture the tuple of S1 and S2. Based on the #2, U would capture the type S.

Which is chosen? Or other choices?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 25, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11124



--- Comment #7 from monarchdodra@gmail.com 2013-09-25 12:23:05 PDT ---
(In reply to comment #6)
> (In reply to comment #4)
> > (In reply to comment #2)
> > > And, how this will work when multiple alias this is properly implemented?
> > 
> > I don't understand the problem? Isn't it the same as, say: "is (C : int)"?
> 
> Today,
> 1. is(T U == super) captures the super class list of T in U.
> 
>   class C : Object {}
>   static if (is(C U == super)) { static assert(is(U[0] == Object)); }
> 
> 2. If T is implicitly convertible to U, is(T X : U) captures T in X.
> 
> Then, if multiple alias this is supported:
> 
>   struct S1 {}
>   struct S2 {}
>   struct S {
>     S1 s1;  alias s1 this;
>     S2 s2;  alias s2 this;
>   }
>   static if (is(S U : struct)) { /* What's captured in U? */ }
> 
> Based on the #1, U would capture the tuple of S1 and S2. Based on the #2, U would capture the type S.
> 
> Which is chosen? Or other choices?

I'm no expert with "is", but isn't "is(C U == super)" a special case of "is"?
(which would look much better as a trait too?)

For example, when I do this;

//----
struct S
{
    short i;
    alias i this;
}

class C
{
    S s;
    alias s this;
}

void main()
{
    static if (is(C U : int))
        static assert(is(U == C)); //Base type C is captured
}
//----

If C was to actually to be:

class C
{
    S s1;
    S s2;
    alias s1 this;
    alias s2 this;
}

I don't see how it would affect my above static if.

Since I don't really see ": int" as any different from ": struct", then to your question, I answer: #2, U would capture the type S.

But I'm no "is" expert.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------