On Sunday, 8 November 2015 at 10:31:13 UTC, Panke wrote:
import std.variant, std.stdio;

---
struct NodeTypeA(T) { T[] children; }
struct NodeTypeB(T) { Tree children; }
struct Leaf(T) { T delegate() dg; }

alias Tree = Algebraic!(Leaf, NodeTypeA!This, NodeTypeB!This);

void main()
{
  Tree t;
}
---

yields

tmp.d(6): Error: functions cannot return opaque type This by value tmp.d(8): Error: template instance tmp.Leaf!(This) error instantiating

This limitation seems arbitrary to me. What's the reason here?

The issue is because your delegate inside Leaf returns a T by value, and T in this case is the type std.variant.This; it's an opaque struct type to allow for recursive structures. If it sees This* or This[] in the template argument list to Algebraic, it'll do some magic to replace this with another Variant. That magic is std.typecons.ReplaceType[1]. However, note the warning on ReplaceType:

"However, member types in `struct`s or `class`es are not replaced because there
are no ways to express the types resulting after replacement."

And thus it can't replace the T return type of your delegate with the proper type. The compiler sees that you're trying to return the opaque struct This by value and violently disagrees with that notion, refusing to compile. To make that particular compiler error go away you can change the return type of the delegate to T* or T[], but that's not particularly useful as you're still just returning a pointer to This, not the recursive type. I'm not completely sure what you're trying to do is possible in D, and definitely not without enhancements to ReplaceType.


1. https://github.com/D-Programming-Language/phobos/blob/245c7ab0b591cb48b3dbb239640dd54e0717110a/std/typecons.d#L6643

Reply via email to