Bug 20009 – isForwardRange doesn't work with alias range this or inheritance

Status
REOPENED
Severity
enhancement
Priority
P4
Component
phobos
Product
D
Version
D2
Platform
x86
OS
Mac OS X
Creation time
2019-06-27T21:24:42Z
Last change time
2024-12-01T16:35:08Z
Keywords
pull
Assigned to
No Owner
Creator
Ali Ak
Moved to GitHub: phobos#10376 →

Comments

Comment #0 by ali.akhtarzada — 2019-06-27T21:24:42Z
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 by dlang-bot — 2019-06-28T07:19:10Z
@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 by shove — 2019-06-29T05:01:15Z
(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 by ali.akhtarzada — 2019-07-08T08:39:26Z
Why mark this invalid? Are interfaces and alias this'd ranges not supposed to work?
Comment #4 by shove — 2019-07-08T09:21:32Z
(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 by robert.schadek — 2024-12-01T16:35:08Z
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