[Issue 20009] isForwardRange doesn't work with alias range this or inheritance

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sat Jun 29 05:01:15 UTC 2019


shove <shove at 163.com> changed:

           What    |Removed                     |Added
                 CC|                            |shove at 163.com

--- Comment #2 from shove <shove at 163.com> ---
(In reply to Ali Ak from comment #0)
> struct FR {
>   bool empty = true;
>   void popFront() {}
>   auto front() { return 0; }
>   FR save() { return this; }
> }
> struct S {
>   FR range;
>   alias range this;
> }
> pragma(msg, isInputRange!S); // true
> pragma(msg, isForwardRange!S); // false
> It's because isForwardRange is defined as:
> isInputRange!R && is(ReturnType!((R r) => r.save) == R);
> But it should be:
> isInputRange!R && is(R : ReturnType!((R r) => r.save));
> The same thing will happen if you try an inherit from an interface that is a
> forward range, and if the save function returns the base class it will fail.

Since struct S inherits from struct FR, I think it should have the
characteristics of ForwardRange too.
But unfortunately, after I do it according to your idea, although struct S
passed the isForwardRange test, it caused a lot of compilation errors in the
entire Phobos, including function code and assertions in unit tests. The
reasons for this include at least the following:

1. is(T1 : T2) is somewhat different than what I have understood before:
    is(R!(int) : int[]) will pass the test, obviously this is not what is
expected here.
2. Too many templates and APIs assume that the return type of save() is exactly
equal to itself, and cannot be equal to the base class. It is equal to the base
class that will overturn these assumptions and cause the program to fail or
assert the failure. Such as:

    std.std.algorithm.searching.d line 3359:
    Range least = range.save;

    Obviously, the base type cannot be assigned to a derived type, and this
assumption has limited the expectations of this issue.

Therefore, if you want isForwardRange to support derived types, then Phobos has
too many places to change, and the workload is a bit large.

It might be a good idea to add a new template to the existing one that is
specifically designed to test derived types with ForwardRange attributes:

template isDerivedForwardRange(R)
    static if (isInputRange!R && is(typeof((R r) => r.save) RT))
        enum bool isForwardRange = !is(R == ReturnType!RT) && is(R :
        enum bool isForwardRange = false;

But I don't know if it has practical use.


More information about the Digitalmars-d-bugs mailing list