Skip to content

Commit aeace12

Browse files
jmdavisdlang-bot
authored andcommitted
Add lvalueOf and rvalueOf to phobos.sys.traits.
These are straight from std.traits but with improvements to the documentation and unit tests. The __InoutWorkaroundStruct bit is kind of ugly, but it does seem to be necessary due to how inout works.
1 parent 23e5d21 commit aeace12

File tree

1 file changed

+92
-7
lines changed

1 file changed

+92
-7
lines changed

phobos/sys/traits.d

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,24 @@
6868
$(LREF isQualifierConvertible)
6969
))
7070
$(TR $(TD Traits for comparisons) $(TD
71-
$(LREF isEqual)
72-
$(LREF isSameSymbol)
73-
$(LREF isSameType)
71+
$(LREF isEqual)
72+
$(LREF isSameSymbol)
73+
$(LREF isSameType)
7474
))
7575
$(TR $(TD Traits for removing type qualfiers) $(TD
7676
$(LREF Unconst)
7777
$(LREF Unshared)
7878
$(LREF Unqualified)
7979
))
8080
$(TR $(TD Type Constructors) $(TD
81-
$(LREF ConstOf)
82-
$(LREF ImmutableOf)
83-
$(LREF InoutOf)
84-
$(LREF SharedOf)
81+
$(LREF ConstOf)
82+
$(LREF ImmutableOf)
83+
$(LREF InoutOf)
84+
$(LREF SharedOf)
85+
))
86+
$(TR $(TD Misc) $(TD
87+
$(LREF lvalueOf)
88+
$(LREF rvalueOf)
8589
))
8690
)
8791
@@ -2658,3 +2662,84 @@ alias SharedOf(T) = shared T;
26582662
shared(bool*), shared(ubyte[]),
26592663
shared(string), immutable(string))));
26602664
}
2665+
2666+
// Needed for rvalueOf/lvalueOf because
2667+
// "inout on return means inout must be on a parameter as well"
2668+
private struct __InoutWorkaroundStruct {}
2669+
2670+
/++
2671+
Creates an lvalue or rvalue of type T to be used in conjunction with
2672+
$(D is(typeof(...))) or
2673+
$(DDSUBLINK spec/traits, compiles, $(D __traits(compiles, ...))).
2674+
2675+
The idea is that some traits or other forms of conditional compilation need
2676+
to verify that a particular piece of code compiles with an rvalue or an
2677+
lvalue of a specific type, and these $(D @property) functions allow you to
2678+
get an rvalue or lvalue of a specific type to use within an expression that
2679+
is then tested to see whether it compiles.
2680+
2681+
They're $(D @property) functions so that using $(D typeof) on them gives
2682+
the return type rather than the type of the function.
2683+
2684+
Note that these functions are $(I not) defined, so if they're actually used
2685+
outside of type introspection, they'll result in linker errors. They're
2686+
entirely for testing that a particular piece of code compiles with an rvalue
2687+
or lvalue of the given type.
2688+
2689+
The $(D __InoutWorkaroundStruct) parameter is entirely to make it so that
2690+
these work when the given type has the $(D inout) qualifier, since the
2691+
language requires that a function that returns an $(D inout) type also have
2692+
an $(D inout) type as a parameter. It should just be ignored.
2693+
+/
2694+
@property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
2695+
2696+
/++ Ditto +/
2697+
@property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
2698+
2699+
///
2700+
@safe unittest
2701+
{
2702+
static int foo(int);
2703+
static assert(is(typeof(foo(lvalueOf!int)) == int));
2704+
static assert(is(typeof(foo(rvalueOf!int)) == int));
2705+
2706+
static bool bar(ref int);
2707+
static assert(is(typeof(bar(lvalueOf!int)) == bool));
2708+
static assert(!is(typeof(bar(rvalueOf!int))));
2709+
2710+
static assert( is(typeof({ lvalueOf!int = 42; })));
2711+
static assert(!is(typeof({ rvalueOf!int = 42; })));
2712+
2713+
static struct S {}
2714+
static assert( is(typeof({ lvalueOf!S = S.init; })));
2715+
static assert(!is(typeof({ rvalueOf!S = S.init; })));
2716+
2717+
static struct NoAssign
2718+
{
2719+
@disable void opAssign(ref NoAssign);
2720+
}
2721+
static assert(!is(typeof({ lvalueOf!NoAssign = NoAssign.init; })));
2722+
static assert(!is(typeof({ rvalueOf!NoAssign = NoAssign.init; })));
2723+
}
2724+
2725+
@system unittest
2726+
{
2727+
import phobos.sys.meta : AliasSeq;
2728+
2729+
void needLvalue(T)(ref T);
2730+
static struct S {}
2731+
int i;
2732+
struct Nested { void f() { ++i; } }
2733+
2734+
static foreach (T; AliasSeq!(int, const int, immutable int, inout int, string, S, Nested, Object))
2735+
{
2736+
static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
2737+
static assert( __traits(compiles, needLvalue(lvalueOf!T)));
2738+
static assert(is(typeof(rvalueOf!T) == T));
2739+
static assert(is(typeof(lvalueOf!T) == T));
2740+
}
2741+
2742+
static assert(!__traits(compiles, rvalueOf!int = 1));
2743+
static assert( __traits(compiles, lvalueOf!byte = 127));
2744+
static assert(!__traits(compiles, lvalueOf!byte = 128));
2745+
}

0 commit comments

Comments
 (0)