www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Difference in compiletime vs compiletime or compiler bug?

reply Sjoerd Nijboer <dlang sjoerdnijboer.com> writes:
I've got a snippet of code which I have narrowed down to the 
following:
'import std.stdio;

enum string[] mixins = ["public bool qux(int i, char c)
             {
                 throw new Exception(\"not implemented\");
                 // Add all arguments to a struct and serialize 
that struct.
             };", "
public bool qux(string s)
             {
                 throw new Exception(\"not implemented\");
                 // Add all arguments to a struct and serialize 
that struct.
             };
			"];

struct C
{
	static foreach (m; mixins)
	{
		mixin mix!m;
	}
}

mixin template mix(string s)
{
	mixin(s);
}

void main()
{
	import std.traits : ReturnType;

	auto c = C();
	pragma(msg, c.qux.mangleof); // writes 'v' to the console
	pragma(msg, ReturnType!(c.qux));
}'

The exact error this returns is as follows:
'Error: template instance std.traits.ReturnType!(qux) does not 
match template declaration ReturnType(func...)
   with func = (qux)
   must satisfy the following constraint:
        isCallable!func
source/app.d(34,2):        while evaluating pragma(msg, 
ReturnType!(qux)
'

As far as I know, this "should" work.
When I delete one of the functions out of the mixin it suddenly 
compiles with a mangled name, but when I place the second 
function in there it won't.
When calling the mixin directly instead of through the template 
mixin it breaks with thesame error message.

I don't know if this an actual compiler bug or if this is me not 
properly understanding D.
I'm using DMD64 D Compiler v2.089.1

Any help is appreciated.
Dec 27 2019
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 27 December 2019 at 18:22:10 UTC, Sjoerd Nijboer wrote:
 When calling the mixin directly instead of through the template 
 mixin it breaks with thesame error message.
What exactly did you do here? struct C { static foreach (m; mixins) { mixin(m); } } works for me...
 I don't know if this an actual compiler bug or if this is me 
 not properly understanding D.
This is a case of the function hijacking rules biting you: https://dlang.org/articles/hijack.html template mixins take things in two different scopes: mix!one_string mix!other_string creates two separate things that do not overload each other. You have to `alias name = xxx` twice in the same scope to merge them. string mixin works differently, it doesn't produce a scope. In your case you probably just want to use string mixin and take the `mix` item out entirely. But anyway the mixin results from the two things do NOT automatically merge whcih is what causes your errors.
Dec 27 2019
parent reply Sjoerd Nijboer <dlang sjoerdnijboer.com> writes:
On Friday, 27 December 2019 at 18:34:49 UTC, Adam D. Ruppe wrote:
 On Friday, 27 December 2019 at 18:22:10 UTC, Sjoerd Nijboer 
 wrote:
 When calling the mixin directly instead of through the 
 template mixin it breaks with thesame error message.
What exactly did you do here?
I meant to say that that is when it does work. I shoul've caught this when I proof-read this post.
 template mixins take things in two different scopes:
 
 mix!one_string
 mix!other_string
 creates two separate things that do not overload each other. 
 You have to `alias name = xxx` twice in the same scope to merge 
 them.
 string mixin works differently, it doesn't produce a scope. In 
 your case you probably just want to use string mixin and take 
 the `mix` item out entirely.
Should concatenating the list and mixing that in work too? I'll probably remove the mixin template completely, concatenate the array of strings and mixin the entire array if that should be the proper way for solving this. Thank you!
Dec 27 2019
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 27 December 2019 at 18:49:32 UTC, Sjoerd Nijboer wrote:
 Should concatenating the list and mixing that in work too?
yeah that'd work too. As long as all the overloads are coming from the same source, D allows it. but if you add something manually in the struct then you have two sources again so this rule can bite back.
Dec 27 2019
parent Sjoerd Nijboer <dlang sjoerdnijboer.com> writes:
On Friday, 27 December 2019 at 18:51:31 UTC, Adam D. Ruppe wrote:
 On Friday, 27 December 2019 at 18:49:32 UTC, Sjoerd Nijboer 
 wrote:
 Should concatenating the list and mixing that in work too?
yeah that'd work too. As long as all the overloads are coming from the same source, D allows it. but if you add something manually in the struct then you have two sources again so this rule can bite back.
It's a completely generated body of a struct, so that won't be an issue. It was just convenient to have a static foreach loop and generate some functions out of that by invoking a mixin template, which will cause the scoping problem. I'll probably generate the `string[]` using a function, join it and then mixin the result to have it all in one scope. I thought I had a valid usecase for mixin templates. :/ They're quite daunting beasts with these kind of constraints.
Dec 27 2019