-
-
Notifications
You must be signed in to change notification settings - Fork 745
Closed
Labels
Description
This should work:
struct R
{
int i;
int front() => i;
bool empty() => i == 0;
void popFront() {--i;}
R save() => this;
}
void main()
{
import std.range;
import std.stdio;
auto rng = R(10).cycle.take(20);
writeln(rng);
}It should output:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
But the code errors with this message:
/dlang/dmd/linux/bin64/../../src/phobos/std/range/package.d(4560): Error: mutable method `onlineapp.R.front` is not callable using a `const` object
return _current.front;
^
onlineapp.d(4): Consider adding `const` or `inout` here
int front() => i;
^
/dlang/dmd/linux/bin64/../../src/phobos/std/range/package.d(4695): Error: template instance `std.range.Cycle!(R)` error instantiating
else return Cycle!R(input);
^
onlineapp.d(14): instantiated from here: `cycle!(R)`
auto rng = R(10).cycle.take(20);
^
The issue is either a compiler bug or an issue with how the library is testing whether it should add a const overload of front.
The code which adds the const front overload is here:
Lines 4562 to 4569 in db880b4
| static if (is(typeof((cast(const R)_current).front))) | |
| { | |
| /// ditto | |
| @property auto ref front() const | |
| { | |
| return _current.front; | |
| } | |
| } |
I see 2 possible gotchas here:
- The
static ifcondition is not doing a reinterpret cast. It is known that the compiler can sometimes just remove constness from rvalues. When I changed the test to using a reinterpret cast, the code compiled (i.e. the wrapper const front method wasn't added), but I don't know if there is some other case that doesn't work correctly. Have to try and see if the PR passes. - The
is(typeof(expr))whereexpris a function symbol name is fraught with ambiguity. Because it could just be checking "does this function exist?" and not "can I call this function on a const object?".
Impetus for this bug report: https://forum.dlang.org/post/hknyezitnsiezjmlappa@forum.dlang.org