May 24, 2023

I'm trying to improve std.array : array to infer whether it's parameter range can be scope. To do this, I need to introspect whether the .front of the range in question is scope. I also need to differentiate plain scope front from scope return or return scope. That is, I need to distinguish the first of these from the latter two:

struct Range
{ // Can point to stack, won't return self-references.
  ElType front() scope;
  // Can point to stack, might return a self-reference or reference to pointed-to data.
  ElType front() scope return;
  // Can point to stack. If so, may return a pointer to stack, but not to this struct itself.
  ElType front() return scope;
}

I tried to solve it this way:

static if(is(typeof((scope Range test, ElementType!Range[] out_) => out_[0] = test.front)))

However, this passes even if range.front is return scope (which I want to fail this test). I suspect it's because scope checks are only done in @safe code. I can't test the assignment for safety since Phobos has to work with ranges that have @system .front or .front.opAssign.

I figured out I need to introspect the parameter storage class of test.front, but how? std.traits : ParameterStorageClassTuple would work, but it doesn't tell the storage classes of the hidden .this pointer - only those of the visible parameters.