Skip to content

std.range.cycle with a forward-range does not compile #10852

@schveiguy

Description

@schveiguy

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:

phobos/std/range/package.d

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:

  1. The static if condition 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.
  2. The is(typeof(expr)) where expr is 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions