Re: A proper WAT moment

2019-10-16 Thread Jacob Carlborg via Digitalmars-d-learn

On 2019-10-15 09:06, John Colvin wrote:

And all the other ones in my example that access members without an 
instance that also compile?


There's something pretty strange about the rules here.


The thing is that it should be possible to access a non-static member 
without an instance because it's possible to manually construct a delegate:


class S
{
int a;
int e() @property { return a; }
}

void foo()
{
int function() f =  // this compiles
int delegate() dg;
S s;
dg.ptr = 
dg.funcptr = f;
}

struct C
{
void bar()
{
int function() f =  // this fails for some reason but 
should compile

}
}

So the expression `S.e` should compile, because it can be part of a 
large expression, i.e. ``, which should compile.


The strange thing is that it fails to compile inside `C`. But if `bar` 
is changed to a static method it compiles again.


--
/Jacob Carlborg


Re: A proper WAT moment

2019-10-15 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 15 October 2019 at 09:34:41 UTC, Simen Kjærås wrote:

void fun() {
pragma(msg, __LINE__, " ", 
__traits(compiles,__traits(getMember, S, "e")));

}


__traits(compiles) is lying to you again. If you replace it with

__traits(getMember, S, "e")

...you'll get an error.



Interestingly, the code does of course actually compile:

struct S3 {
void fun() {
alias a = __traits(getMember, S, "e");
}
}


I think this is the key. It compiles if you put it on the 
right-hand side of an alias declaration, but *not* if you write 
it as a bare expression:


struct S3 {
void fun() {
__traits(getMember, S, "e"); // Error
}
}

The difference is that in an alias declaration, 
__traits(getMember) isn't evaluated as a function call, whereas 
in a naked expression, it is. So the question becomes, why is 
__traits(getMember) evaluating @property functions differently in 
different contexts?


I suspect the answer has to do with the difference between the 
two error messages. In the context of a free function, it's "need 
`this` for `e`"--i.e., you're calling a member function without a 
receiver--so the compiler can infer that you didn't mean to call 
the function at all. In the context of a member function, 
however, it's "`this` needs to be type `S`, not `S2`"--i.e., 
you're (implicitly) calling a member function on the wrong type 
of receiver--so the compiler treats it the same as any other 
function call with incorrect arguments, and assumes you actually 
meant it.


Of course, this is speculation; it would take looking at the 
compiler source to be sure.


Re: A proper WAT moment

2019-10-15 Thread Simen Kjærås via Digitalmars-d-learn

On Tuesday, 15 October 2019 at 07:06:35 UTC, John Colvin wrote:

On Monday, 14 October 2019 at 19:45:11 UTC, Paul Backus wrote:

On Monday, 14 October 2019 at 17:00:56 UTC, John Colvin wrote:
Different ability to access a property depending if I'm 
inside something else when I look?


[snip]


You're attempting to call one of S's member functions without 
an instance of S to call it on.

[snip]
The real issue here is that the first `__traits(compiles)` 
check succeeds, even though the actual expression fails.


And all the other ones in my example that access members 
without an instance that also compile?


There's something pretty strange about the rules here.


Yeah, Paul's wrong here - the struct is what messes things up 
here, though I don't understand why. Just putting the first 
function inside a struct cause the exact same issue:


struct S {
int a;
int e() @property { return a; }
}

pragma(msg, __LINE__, " ", __traits(compiles,__traits(getMember, 
S, "e")));


void fun() {
pragma(msg, __LINE__, " ", 
__traits(compiles,__traits(getMember, S, "e")));

}

struct S2 {
void fun() {
pragma(msg, __LINE__, " ", 
__traits(compiles,__traits(getMember, S, "e")));

}
}

Interestingly, the code does of course actually compile:

struct S3 {
void fun() {
alias a = __traits(getMember, S, "e");
}
}


Re: A proper WAT moment

2019-10-15 Thread John Colvin via Digitalmars-d-learn

On Monday, 14 October 2019 at 19:45:11 UTC, Paul Backus wrote:

On Monday, 14 October 2019 at 17:00:56 UTC, John Colvin wrote:
Different ability to access a property depending if I'm inside 
something else when I look?


[snip]


You're attempting to call one of S's member functions without 
an instance of S to call it on. Reduced version:


struct S
{
int a;
int e() @property { return a; }
}

void foo(S s)
{
pragma(msg, __LINE__, " ", __traits(compiles, S.e)); // 
true (???)

S.e; // Error: need `this` for `e` of type `@property int()`
}

struct C
{
void foo(S s)
{
pragma(msg, __LINE__, " ", __traits(compiles, S.e)); // 
false
S.e; // Error: `this` for `e` needs to be type `S` not 
type `C`

}
}

The real issue here is that the first `__traits(compiles)` 
check succeeds, even though the actual expression fails.


And all the other ones in my example that access members without 
an instance that also compile?


There's something pretty strange about the rules here.


Re: A proper WAT moment

2019-10-14 Thread Paul Backus via Digitalmars-d-learn

On Monday, 14 October 2019 at 17:00:56 UTC, John Colvin wrote:
Different ability to access a property depending if I'm inside 
something else when I look?


[snip]


You're attempting to call one of S's member functions without an 
instance of S to call it on. Reduced version:


struct S
{
int a;
int e() @property { return a; }
}

void foo(S s)
{
pragma(msg, __LINE__, " ", __traits(compiles, S.e)); // true 
(???)

S.e; // Error: need `this` for `e` of type `@property int()`
}

struct C
{
void foo(S s)
{
pragma(msg, __LINE__, " ", __traits(compiles, S.e)); // 
false
S.e; // Error: `this` for `e` needs to be type `S` not 
type `C`

}
}

The real issue here is that the first `__traits(compiles)` check 
succeeds, even though the actual expression fails.


A proper WAT moment

2019-10-14 Thread John Colvin via Digitalmars-d-learn
Different ability to access a property depending if I'm inside 
something else when I look?


struct S
{
int a;
static int b;
int c() { return a; }
static int d() { return 3; }
int e() @property { return a; }
static int f() @property { return 3; }
}

void foo(S s)
{
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "a")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "a")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "b")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "b")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "c")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "c")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "d")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "d")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "e")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "e")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "f")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "f")));

}

struct C(S)
{
void foo(S s)
{
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "a")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "a")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "b")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "b")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "c")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "c")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "d")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "d")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "e")));

// ALL True except for this one:
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "e")));


pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, s, "f")));
pragma(msg, __LINE__, " ", __traits(compiles, 
__traits(getMember, S, "f")));

}
}

alias C0 = C!S;