Thread overview
Difference in compiletime vs compiletime or compiler bug?
Dec 27, 2019
Sjoerd Nijboer
Dec 27, 2019
Adam D. Ruppe
Dec 27, 2019
Sjoerd Nijboer
Dec 27, 2019
Adam D. Ruppe
Dec 27, 2019
Sjoerd Nijboer
December 27, 2019
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.
December 27, 2019
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.
December 27, 2019
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!
December 27, 2019
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.
December 27, 2019
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.