[Issue 22010] New: Link error with mutually recursive SumType / struct with opEquals
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Wed Jun 9 06:23:46 UTC 2021
https://issues.dlang.org/show_bug.cgi?id=22010
Issue ID: 22010
Summary: Link error with mutually recursive SumType / struct
with opEquals
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Keywords: link-failure
Severity: normal
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: dlang-bugzilla at thecybershadow.net
///////////////////////////////////// test.d
////////////////////////////////////
import std.sumtype;
struct S { Ref!Node node; }
alias Node = SumType!S;
private struct Ref(T)
{
private T* _ref_ptr;
this(ref T value) { _ref_ptr = &value; } ///
bool opEquals(ref const Ref!T other) { return *_ref_ptr == *other._ref_ptr;
}
}
void main() {}
/////////////////////////////////////////////////////////////////////////////////
This produces:
---
/usr/sbin/ld: test.o: in function
`_D3std7sumtype__T7SumTypeTS4test1SZQs__T8opEqualsTSQBxQBw__TQBrTQBmZQBzTxSQCuQCt__TQCoTQCjZQCwZQCdMFKxQBdZb':
test.d:(.text._D3std7sumtype__T7SumTypeTS4test1SZQs__T8opEqualsTSQBxQBw__TQBrTQBmZQBzTxSQCuQCt__TQCoTQCjZQCwZQCdMFKxQBdZb[_D3std7sumtype__T7SumTypeTS4test1SZQs__T8opEqualsTSQBxQBw__TQBrTQBmZQBzTxSQCuQCt__TQCoTQCjZQCwZQCdMFKxQBdZb]+0x21):
undefined reference to
`_D3std7sumtype__T7SumTypeTS4test1SZQs__T8opEqualsTxSQByQBx__TQBsTQBnZQCaTxQxZQBlMxFNbKxQBkZb'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1
---
Demangled:
---
/usr/sbin/ld: test.o: in function `bool
std.sumtype.SumType!(test.S).SumType.opEquals!(std.sumtype.SumType!(test.S).SumType,
const(std.sumtype.SumType!(test.S).SumType)).opEquals(ref
const(std.sumtype.SumType!(test.S).SumType))':
test.d:(.text.bool
std.sumtype.SumType!(test.S).SumType.opEquals!(std.sumtype.SumType!(test.S).SumType,
const(std.sumtype.SumType!(test.S).SumType)).opEquals(ref
const(std.sumtype.SumType!(test.S).SumType))[bool
std.sumtype.SumType!(test.S).SumType.opEquals!(std.sumtype.SumType!(test.S).SumType,
const(std.sumtype.SumType!(test.S).SumType)).opEquals(ref
const(std.sumtype.SumType!(test.S).SumType))]+0x21): undefined reference to
`const nothrow bool
std.sumtype.SumType!(test.S).SumType.opEquals!(const(std.sumtype.SumType!(test.S).SumType),
const(std.sumtype.SumType!(test.S).SumType)).opEquals(ref
const(std.sumtype.SumType!(test.S).SumType))'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1
---
After dustmite-ing std.sumtype:
/////////////////////////////////// test.d //////////////////////////////////
import std.meta: AliasSeq, Map = staticMap;
import std.traits ;
import std.typecons ;
struct This {}
struct SumType(Types)
{
alias Types = AliasSeq!(
ReplaceTypeUnless!(
isSumTypeInstance,
This,
typeof(this),
TemplateArgsOf!SumType)
);
union Storage
{
// Workaround for https://issues.dlang.org/show_bug.cgi?id=20068
template memberName(T)
{
mixin("enum memberName = `values_", "`;");
}
static foreach (T; Types)
mixin("T ", memberName!T, ";");
}
Storage storage;
inout(T) get(T)() inout
{
return __traits(getMember, storage, Storage.memberName!T);
}
bool opEquals(this This, Rhs)(Rhs rhs)
{
static if (is(This == Rhs))
AliasSeq!(this, rhs).match!((value, rhsValue) {
value == rhsValue;
});
alias CommonSumType = Rhs;
return cast(CommonSumType) this == rhs;
}
}
enum isSumTypeInstance(T) = is(Args);
template match(handlers...)
{
auto match(SumTypes...)(SumTypes args)
{
matchImpl!handlers(args);
}
}
template canMatch(alias handler, Ts...)
{
enum canMatch = (Ts args) => handler(args);
}
template Iota(size_t n)
{
alias Iota = AliasSeq!(1, 1);
}
template matchImpl(handlers...)
{
auto matchImpl(SumTypes...)(SumTypes args)
{
struct TagTuple
{
size_t[SumTypes.length] tags;
alias tags this;
static fromCaseId()
{
TagTuple result;
// Most-significant to least-significant
static foreach(i; 0 .. result.length)
return result;
}
}
template valueTypes(size_t caseId)
{
enum tags = TagTuple.fromCaseId;
template getType(size_t i)
{
alias T = SumTypes[i].Types;
alias getType = typeof(args[i].get!T());
}
alias valueTypes = Map!(getType, Iota!(tags.length));
}
enum numCases = SumTypes.length;
static foreach (caseId; 0 .. numCases)
foreach (handler; handlers)
static if (canMatch!(handler, valueTypes!caseId))
{
}
}
}
struct S { Ref!Node node; }
alias Node = SumType!S;
struct Ref(T)
{
T* _ref_ptr;
bool opEquals(const Ref!T other) { return *_ref_ptr == *other._ref_ptr; }
}
/////////////////////////////////////////////////////////////////////////////
--
More information about the Digitalmars-d-bugs
mailing list