Issue 20009 - isForwardRange doesn't work with alias range this or inheritance
Summary: isForwardRange doesn't work with alias range this or inheritance
Status: REOPENED
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: x86 Mac OS X
: P4 enhancement
Assignee: No Owner
URL:
Keywords: pull
Depends on:
Blocks:
 
Reported: 2019-06-27 21:24 UTC by Ali Ak
Modified: 2024-12-01 16:35 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Ali Ak 2019-06-27 21:24:42 UTC
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.
Comment 1 Dlang Bot 2019-06-28 07:19:10 UTC
@shove70 created dlang/phobos pull request #7095 "Fix issue 20009 - isForwardRange doesn't work with alias range this o…" fixing this issue:

- Fix issue 20009 - isForwardRange doesn't work with alias range this or inheritance

https://github.com/dlang/phobos/pull/7095
Comment 2 shove 2019-06-29 05:01:15 UTC
(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 : ReturnType!RT);
    else
        enum bool isForwardRange = false;
}

But I don't know if it has practical use.
Comment 3 Ali Ak 2019-07-08 08:39:26 UTC
Why mark this invalid? Are interfaces and alias this'd ranges not supposed to work?
Comment 4 shove 2019-07-08 09:21:32 UTC
(In reply to Ali Ak from comment #3)
> Why mark this invalid? Are interfaces and alias this'd ranges not supposed
> to work?

Misread the title and misoperate it. I'm sorry.
Comment 5 dlangBugzillaToGithub 2024-12-01 16:35:08 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/phobos/issues/10376

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB