Thread overview
opDispatch compiles fine, but still fails to resolve?
Aug 09, 2014
Vlad Levenfeld
Aug 09, 2014
Meta
Aug 09, 2014
Vlad Levenfeld
Aug 09, 2014
H. S. Teoh
Aug 09, 2014
Vlad Levenfeld
Aug 09, 2014
Artur Skawina
Aug 09, 2014
Vlad Levenfeld
August 09, 2014
More opDispatch woes. This feature keeps biting me, yet I keep trying to use it.

This time I'm trying to access elements of a vector GLSL-style (without swizzling... for now).

Here's the relevant code:

struct Vector (uint length, Element = double)
{
		ref @property component (string c)()
		{
			enum mat = q{xyzw};
			enum col = q{rgba};
			enum tex = q{uv};

			static if (mat.canFind (c))
				return components[mat.countUntil (c)];
			else static if (col.canFind (c))
				return components[col.countUntil (c)];
			else static if (tex.canFind (c))
				return components[tex.countUntil (c)];
			else static assert (0);
		}

		ref @property opDispatch (string c)()
		if (c.length == 1)
		{
			auto v = component!c;
			pragma(msg, typeof(v)); // this outputs the expected result
			return v; // so everything is fine, right? wrong...
		}

	Element[length] components;
}

Calling vector.component!`x` or something works fine, but calling vector.x fails with "Error: no property" etc.

Now, I'm used to opDispatch silently failing when it can't compile (very annoying btw), but in this case, I tested every line with a pragma (msg, __traits(compiles...)) and everything checks out. All expressions are verified CTFE-able. The compiler apparently makes it all the way through the method without a hitch, but then just fails symbol resolution anyway.

Is this just a bug? Does anyone have any advice on what else to try? I'm out of ideas (short of falling back on generating property methods by string mixin).
August 09, 2014
On Saturday, 9 August 2014 at 01:20:33 UTC, Vlad Levenfeld wrote:
> More opDispatch woes. This feature keeps biting me, yet I keep trying to use it.
>
> This time I'm trying to access elements of a vector GLSL-style (without swizzling... for now).
>
> Here's the relevant code:
>
> struct Vector (uint length, Element = double)
> {
> 		ref @property component (string c)()
> 		{
> 			enum mat = q{xyzw};
> 			enum col = q{rgba};
> 			enum tex = q{uv};
>
> 			static if (mat.canFind (c))
> 				return components[mat.countUntil (c)];
> 			else static if (col.canFind (c))
> 				return components[col.countUntil (c)];
> 			else static if (tex.canFind (c))
> 				return components[tex.countUntil (c)];
> 			else static assert (0);
> 		}
>
> 		ref @property opDispatch (string c)()
> 		if (c.length == 1)
> 		{
> 			auto v = component!c;
> 			pragma(msg, typeof(v)); // this outputs the expected result
> 			return v; // so everything is fine, right? wrong...
> 		}
>
> 	Element[length] components;
> }
>
> Calling vector.component!`x` or something works fine, but calling vector.x fails with "Error: no property" etc.
>
> Now, I'm used to opDispatch silently failing when it can't compile (very annoying btw), but in this case, I tested every line with a pragma (msg, __traits(compiles...)) and everything checks out. All expressions are verified CTFE-able. The compiler apparently makes it all the way through the method without a hitch, but then just fails symbol resolution anyway.
>
> Is this just a bug? Does anyone have any advice on what else to try? I'm out of ideas (short of falling back on generating property methods by string mixin).

Have you tried it without @property? It's probably that which is causing the "Error: no property" message. As far as I know, opDispatch *only* works for variable-like access (i.e., vector.x), so making it @property is unnecessary and probably, in this case, buggy.
August 09, 2014
Yep, replacing @property with auto did the trick.

The lack of error messages in opDispatch is frustrating. I realize that, due to tricks like __traits(compiles, Foo.testing_for_some_function), having opDispatch stop compilation if it fails is not going to work, but there's gotta be some way to expose what's going on with it when it fails. Maybe some kind of pragma to cause opDispatch to report its failures, I don't know.
August 09, 2014
On Sat, Aug 09, 2014 at 05:34:40AM +0000, Vlad Levenfeld via Digitalmars-d-learn wrote:
> Yep, replacing @property with auto did the trick.
> 
> The lack of error messages in opDispatch is frustrating. I realize that, due to tricks like __traits(compiles, Foo.testing_for_some_function), having opDispatch stop compilation if it fails is not going to work, but there's gotta be some way to expose what's going on with it when it fails. Maybe some kind of pragma to cause opDispatch to report its failures, I don't know.

Why would having opDispatch actually generate compile errors cause
problems for __traits(compiles,...)? __traits(compiles...) already works
fine with a whole bunch of other non-compiling stuff (by gagging errors
while it attempts them).

The problem with opDispatch is that it gags too much, even when the resolution ultimately fails, so you're left with mysterious "disappearances" of opDispatch with no hint as to what went wrong. I'm not familiar with this part of DMD, but surely there's a way to make this behave better??


T

-- 
"The number you have dialed is imaginary. Please rotate your phone 90 degrees and try again."
August 09, 2014
On 08/09/14 03:20, Vlad Levenfeld via Digitalmars-d-learn wrote:
> More opDispatch woes. This feature keeps biting me, yet I keep trying to use it.
> 
> This time I'm trying to access elements of a vector GLSL-style (without swizzling... for now).
> 
> Here's the relevant code:
> 
> struct Vector (uint length, Element = double)
> {
>         ref @property component (string c)()
>         {
>             enum mat = q{xyzw};
>             enum col = q{rgba};
>             enum tex = q{uv};
> 
>             static if (mat.canFind (c))
>                 return components[mat.countUntil (c)];
>             else static if (col.canFind (c))
>                 return components[col.countUntil (c)];
>             else static if (tex.canFind (c))
>                 return components[tex.countUntil (c)];
>             else static assert (0);
>         }
> 
>         ref @property opDispatch (string c)()
>         if (c.length == 1)
>         {
>             auto v = component!c;
>             pragma(msg, typeof(v)); // this outputs the expected result
>             return v; // so everything is fine, right? wrong...
>         }
> 
>     Element[length] components;
> }
> 
> Calling vector.component!`x` or something works fine, but calling vector.x fails with "Error: no property" etc.
> 
> Now, I'm used to opDispatch silently failing when it can't compile (very annoying btw), but in this case, I tested every line with a pragma (msg, __traits(compiles...)) and everything checks out. All expressions are verified CTFE-able. The compiler apparently makes it all the way through the method without a hitch, but then just fails symbol resolution anyway.
> 
> Is this just a bug? Does anyone have any advice on what else to try?

v.opDispatch!`x`;

Your opDispatch is returning a reference to a local stack-allocated variable. D does not support real references; that 'auto v=...' declaration creates a copy.

   ref @property opDispatch (string c)() { return component!c; }

[opDispatch works for every kind of symbol, there's no problem with
 @property]

artur
August 09, 2014
On Saturday, 9 August 2014 at 10:36:55 UTC, Artur Skawina via Digitalmars-d-learn wrote:
> On 08/09/14 03:20, Vlad Levenfeld via Digitalmars-d-learn wrote:
>> More opDispatch woes. This feature keeps biting me, yet I keep trying to use it.
>> 
>> This time I'm trying to access elements of a vector GLSL-style (without swizzling... for now).
>> 
>> Here's the relevant code:
>> 
>> struct Vector (uint length, Element = double)
>> {
>>         ref @property component (string c)()
>>         {
>>             enum mat = q{xyzw};
>>             enum col = q{rgba};
>>             enum tex = q{uv};
>> 
>>             static if (mat.canFind (c))
>>                 return components[mat.countUntil (c)];
>>             else static if (col.canFind (c))
>>                 return components[col.countUntil (c)];
>>             else static if (tex.canFind (c))
>>                 return components[tex.countUntil (c)];
>>             else static assert (0);
>>         }
>> 
>>         ref @property opDispatch (string c)()
>>         if (c.length == 1)
>>         {
>>             auto v = component!c;
>>             pragma(msg, typeof(v)); // this outputs the expected result
>>             return v; // so everything is fine, right? wrong...
>>         }
>> 
>>     Element[length] components;
>> }
>> 
>> Calling vector.component!`x` or something works fine, but calling vector.x fails with "Error: no property" etc.
>> 
>> Now, I'm used to opDispatch silently failing when it can't compile (very annoying btw), but in this case, I tested every line with a pragma (msg, __traits(compiles...)) and everything checks out. All expressions are verified CTFE-able. The compiler apparently makes it all the way through the method without a hitch, but then just fails symbol resolution anyway.
>> 
>> Is this just a bug? Does anyone have any advice on what else to try?
>
> v.opDispatch!`x`;
>
> Your opDispatch is returning a reference to a local stack-allocated
> variable. D does not support real references; that 'auto v=...'
> declaration creates a copy.
>
>    ref @property opDispatch (string c)() { return component!c; }
>
> [opDispatch works for every kind of symbol, there's no problem with
>  @property]
>
> artur

Yeah, sorry, I made that change last-minute to verify, with the pragma, that I was indeed getting the correct type. The problem must have been something else. I just made a complete oversight in the process of throwing everything but the kitchen sink into debugging it.
August 09, 2014
On Saturday, 9 August 2014 at 05:42:09 UTC, H. S. Teoh via Digitalmars-d-learn wrote:
> Why would having opDispatch actually generate compile errors cause
> problems for __traits(compiles,...)? __traits(compiles...) already works
> fine with a whole bunch of other non-compiling stuff (by gagging errors
> while it attempts them).
>
> The problem with opDispatch is that it gags too much, even when the
> resolution ultimately fails, so you're left with mysterious
> "disappearances" of opDispatch with no hint as to what went wrong. I'm
> not familiar with this part of DMD, but surely there's a way to make
> this behave better??
>
>
> T

You're right, between you and Artur and a night's rest I'm realizing what an utter mess my post was. At that point I had lost half a day debugging this and hadn't slept much so my thought process was not particularly coherent.

The only thing I've ever really managed to get out of opDispatch in terms of errors is to litter the thing with pragma(msg, ...) and hope that, on visual inspection, something clicks and I can figure out where I went wrong.

I think the real crux of my issue was misunderstanding "auto ref". After I noticed that I could use "const" or "@property" or some other qualifier instead of auto, I assumed that it implied auto, so that ref @property => auto ref @property. Evidently not. I was looking inside the method body for the issue when it was on that first line the whole time.