Skip to content

Commit

Permalink
Fix issue 21253 - Can't compile Variant.visit!(...) with generic func…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
Biotronic authored and dlang-bot committed Oct 31, 2020
1 parent 5ce45f9 commit 6ee10a4
Showing 1 changed file with 35 additions and 8 deletions.
43 changes: 35 additions & 8 deletions std/variant.d
Original file line number Diff line number Diff line change
Expand Up @@ -2483,11 +2483,11 @@ if (Handlers.length > 0)

Algebraic!(int, string) maybenumber = 2;
// ok, x ~ "a" valid for string, x + 1 valid for int, only 1 generic
static assert( __traits(compiles, number.visit!((string x) => x ~ "a", x => x + 1)));
static assert( __traits(compiles, maybenumber.visit!((string x) => x ~ "a", x => "foobar"[0 .. x + 1])));
// bad, x ~ "a" valid for string but not int
static assert(!__traits(compiles, number.visit!(x => x ~ "a")));
static assert(!__traits(compiles, maybenumber.visit!(x => x ~ "a")));
// bad, two generics, each only applies in one case
static assert(!__traits(compiles, number.visit!(x => x + 1, x => x ~ "a")));
static assert(!__traits(compiles, maybenumber.visit!(x => x + 1, x => x ~ "a")));
}

/**
Expand Down Expand Up @@ -2596,6 +2596,24 @@ if (isAlgebraic!VariantType && Handler.length > 0)

Result result;

enum int nonmatch = ()
{
foreach (int dgidx, dg; Handler)
{
bool found = false;
foreach (T; AllowedTypes)
{
found |= __traits(compiles, { static assert(isSomeFunction!(dg!T)); });
found |= __traits(compiles, (T t) { dg(t); });
found |= __traits(compiles, dg());
}
if (!found) return dgidx;
}
return -1;
}();
static assert(nonmatch == -1, "No match for visit handler #"~
nonmatch.stringof~" ("~Handler[nonmatch].stringof~")");

foreach (tidx, T; AllowedTypes)
{
bool added = false;
Expand Down Expand Up @@ -2627,18 +2645,14 @@ if (isAlgebraic!VariantType && Handler.length > 0)
result.indices[tidx] = dgidx;
}
}
else static if (isSomeFunction!(dg!T))
else static if (__traits(compiles, { static assert(isSomeFunction!(dg!T)); }))
{
assert(result.generalFuncIdx == -1 ||
result.generalFuncIdx == dgidx,
"Only one generic visitor function is allowed");
result.generalFuncIdx = dgidx;
}
// Handle composite visitors with opCall overloads
else
{
static assert(false, dg.stringof ~ " is not a function or delegate");
}
}

if (!added)
Expand Down Expand Up @@ -2692,6 +2706,19 @@ if (isAlgebraic!VariantType && Handler.length > 0)
assert(false);
}

// https://issues.dlang.org/show_bug.cgi?id=21253
@system unittest
{
static struct A { int n; }
static struct B { }

auto a = Algebraic!(A, B)(B());
assert(a.visit!(
(B _) => 42,
(a ) => a.n
) == 42);
}

@system unittest
{
// validate that visit can be called with a const type
Expand Down

0 comments on commit 6ee10a4

Please sign in to comment.