Thread overview
Help needed for "recursive template expansion error"
Oct 21, 2019
Anthony Abeo
Oct 21, 2019
Nicholas Wilson
Oct 22, 2019
Anthony Abeo
Oct 22, 2019
Simen Kjærås
Oct 23, 2019
Anthony Abeo
October 21, 2019
Hello all,

I have an Algebraic type of structs as shown below. One of the structs is the `Code` struct and this struct holds an array of ATTR_INFO. It is self-referential. Obviously the compiler is unable to get the maximum size of ATTR_INFO at compile-time, hence throwing the error. I will be very grateful for any help to resolve this issue.

alias ATTR_INFO = Algebraic!(SourceFile, ConstantValue, Excepsion, Code,
                                                    LineNumberTable, LocalVariableTable);

struct Code
{
	size_t attribute_name_index;
	size_t attribute_len;
	size_t max_stack;
	size_t max_locals;
	size_t code_length;
	const(ubyte[]) code;
	size_t exception_table_length;
	Tuple!(size_t, size_t, size_t, size_t) exception_table;
	size_t attribute_count;
	ATTR_INFO[] attributes;
}

STACK TRACE
/Library/D/dmd/src/phobos/std/variant.d(1517,23): Error: template instance `VariantN!(maxSize!(SourceFile, ConstantV
alue, Excepsion, Code, LineNumberTable, LocalVariableTable), T)` recursive template expansion
/Library/D/dmd/src/phobos/std/variant.d(87,48): Error: template instance `std.variant.maxSize!(Code, LineNumberTable
, LocalVariableTable)` error instantiating
/Library/D/dmd/src/phobos/std/variant.d(87,48):        instantiated from here: maxSize!(Excepsion, Code, LineNumberT
able, LocalVariableTable)
/Library/D/dmd/src/phobos/std/variant.d(87,48):        instantiated from here: maxSize!(ConstantValue, Excepsion, Code, LineNumberTable, LocalVariableTable)
/Library/D/dmd/src/phobos/std/variant.d(1517,33):        instantiated from here: maxSize!(SourceFile, ConstantValue, Excepsion, Code, LineNumberTable, LocalVariableTable)
source/app.d(8,19):        instantiated from here: Algebraic!(SourceFile, ConstantValue, Excepsion, Code, LineNumberTable, LocalVariableTable)
/Library/D/dmd/bin/dmd failed with exit code 1.
October 21, 2019
On Monday, 21 October 2019 at 18:14:11 UTC, Anthony Abeo wrote:
> Hello all,
>
> I have an Algebraic type of structs as shown below. One of the structs is the `Code` struct and this struct holds an array of ATTR_INFO. It is self-referential. Obviously the compiler is unable to get the maximum size of ATTR_INFO at compile-time, hence throwing the error. I will be very grateful for any help to resolve this issue.
>
> alias ATTR_INFO = Algebraic!(SourceFile, ConstantValue, Excepsion, Code,
>                                                     LineNumberTable, LocalVariableTable);
>
> struct Code
> {
> 	size_t attribute_name_index;
> 	size_t attribute_len;
> 	size_t max_stack;
> 	size_t max_locals;
> 	size_t code_length;
> 	const(ubyte[]) code;
> 	size_t exception_table_length;
> 	Tuple!(size_t, size_t, size_t, size_t) exception_table;
> 	size_t attribute_count;
> 	ATTR_INFO[] attributes;
> }

Please post such questions to the learn forum in the future.

One way to fix this is to use the `This` type to perform type substitution in the Algebraic which refers to the final type of the Algebraic, used like `alias F = Algebraic!(int, string, This[])`.  Where F is either an int, a string or an array of Fs.

You could probably remove `attributes` from code and use

alias ATTR_INFO = Algebraic!(SourceFile, ConstantValue,  Excepsion, Tuple!(Code,This[]), LineNumberTable, LocalVariableTable);

October 22, 2019
On Monday, 21 October 2019 at 18:45:44 UTC, Nicholas Wilson wrote:
> On Monday, 21 October 2019 at 18:14:11 UTC, Anthony Abeo wrote:
>> [...]
>
> Please post such questions to the learn forum in the future.
>
> One way to fix this is to use the `This` type to perform type substitution in the Algebraic which refers to the final type of the Algebraic, used like `alias F = Algebraic!(int, string, This[])`.  Where F is either an int, a string or an array of Fs.
>
> You could probably remove `attributes` from code and use
>
> alias ATTR_INFO = Algebraic!(SourceFile, ConstantValue,  Excepsion, Tuple!(Code,This[]), LineNumberTable, LocalVariableTable);

- Please post such questions to the learn forum in the future.
Noted. I will do that next time.

I tried your suggestion and it fails silently; no error message / stack trace.
October 22, 2019
On Tuesday, 22 October 2019 at 08:16:47 UTC, Anthony Abeo wrote:
> On Monday, 21 October 2019 at 18:45:44 UTC, Nicholas Wilson wrote:
>> On Monday, 21 October 2019 at 18:14:11 UTC, Anthony Abeo wrote:
>>> [...]
>>
>> Please post such questions to the learn forum in the future.
>>
>> One way to fix this is to use the `This` type to perform type substitution in the Algebraic which refers to the final type of the Algebraic, used like `alias F = Algebraic!(int, string, This[])`.  Where F is either an int, a string or an array of Fs.
>>
>> You could probably remove `attributes` from code and use
>>
>> alias ATTR_INFO = Algebraic!(SourceFile, ConstantValue,  Excepsion, Tuple!(Code,This[]), LineNumberTable, LocalVariableTable);
>
> - Please post such questions to the learn forum in the future.
> Noted. I will do that next time.
>
> I tried your suggestion and it fails silently; no error message / stack trace.

I'd suggest using SumType (https://code.dlang.org/packages/sumtype) instead of std.variant, as the latter has its share of problems.

Otherwise, this kinda works, but can hardly be called anything but a horrible hack:

alias ATTR_INFO = Algebraic!(SourceFile, ConstantValue, Excepsion, Code,
                             LineNumberTable, LocalVariableTable);

struct Code
{
	size_t attribute_name_index;
	size_t attribute_len;
	size_t max_stack;
	size_t max_locals;
	size_t code_length;
	const(ubyte[]) code;
	size_t exception_table_length;
	Tuple!(size_t, size_t, size_t, size_t) exception_table;
	size_t attribute_count;
	private ubyte[] _attributes;
}

ref ATTR_INFO[] attributes(return ref Code code)
{
    return *cast(ATTR_INFO[]*)&code._attributes;
}

It will need some fixing if you have any destructors, as Code treats those ATTR_INFOs as just a bunch of bytes, but it will make the code compile and it might be good enough. Seriously though, check out SumType instead.

--
  Simen
October 23, 2019
On Tuesday, 22 October 2019 at 08:42:48 UTC, Simen Kjærås wrote:
> On Tuesday, 22 October 2019 at 08:16:47 UTC, Anthony Abeo wrote:
>> [...]
>
> I'd suggest using SumType (https://code.dlang.org/packages/sumtype) instead of std.variant, as the latter has its share of problems.
>
> [...]

Thanks Simen.

the sumtype package helped.

Thanks everyone.