Thread overview
Cannot call find with haystack elements having a explicit copy constructors
Jul 15
RazvanN
July 15

The adding of copy construtors to Service defined as

@safe struct Service {
    this(ref return scope typeof(this) rhs) {}
    this(const ref return scope typeof(this) rhs) const {}
}

@safe struct Session {
    void openAndGetService(in string key) scope {
        import std.algorithm.searching : find;
        auto hit = _pairs.find!((x) => x.key == key)();
    }
    private Pair[] _pairs;
    private struct Pair {
        string key;
        Service service;
    }
}

makes a call to find error as

copy_ctor_find_fail.d(9): Error: template `std.algorithm.searching.find` cannot deduce function from argument types `!((x) => x.key == key)(Pair[])`, candidates are:
auto hit = _pairs.find!((x) => x.key == key)();
^
std/algorithm/searching.d(1559):        `find(alias pred = "a == b", InputRange, Element)(InputRange haystack, scope Element needle)`
InputRange find(alias pred = "a == b", InputRange, Element)(InputRange haystack, scope Element needle)
^
std/algorithm/searching.d(1827):        `find(alias pred, InputRange)(InputRange haystack)`
with `pred = __lambda2,
InputRange = Pair[]`
must satisfy the following constraint:
`       isInputRange!InputRange`
InputRange find(alias pred, InputRange)(InputRange haystack)
^
std/algorithm/searching.d(1881):        `find(alias pred = "a == b", R1, R2)(R1 haystack, scope R2 needle)`
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, scope R2 needle)
^
std/algorithm/searching.d(2340):        `find(alias pred = "a == b", Range, Ranges...)(Range haystack, Ranges needles)`
with `pred = __lambda2,
Range = Pair[],
Ranges = ()`
must satisfy the following constraint:
`       Ranges.length > 1`
Tuple!(Range, size_t) find(alias pred = "a == b", Range, Ranges...)
^
std/algorithm/searching.d(2455):        `find(RandomAccessRange, alias pred, InputRange)(RandomAccessRange haystack, scope BoyerMooreFinder!(pred, InputRange) needle)`
RandomAccessRange find(RandomAccessRange, alias pred, InputRange)(
^```
Using

```d
auto hit = _pairs.find!((scope const ref x) => x.key == key)();

fails in the same way. What's wrong?

July 15

On Thursday, 15 July 2021 at 11:08:25 UTC, Per Nordlöw wrote:

>

fails in the same way. What's wrong?

@safe struct Service {
    this(ref typeof(this) rhs) {}
    this(const ref typeof(this) rhs) const {}
}

also fails. On the other hand, using a postblit as

@safe struct Service {
    this(this) {}
}

passes.

July 15

On Thursday, 15 July 2021 at 11:08:25 UTC, Per Nordlöw wrote:

>

The adding of copy construtors to Service defined as

@safe struct Service {
    this(ref return scope typeof(this) rhs) {}
    this(const ref return scope typeof(this) rhs) const {}
}

Using inout as

@safe struct Service {
    this(inout ref typeof(this) rhs) inout {}
}

works.

July 15

On Thursday, 15 July 2021 at 11:08:25 UTC, Per Nordlöw wrote:

>

The adding of copy construtors to Service defined as

@safe struct Service {
    this(ref return scope typeof(this) rhs) {}
    this(const ref return scope typeof(this) rhs) const {}
}

@safe struct Session {
    void openAndGetService(in string key) scope {
        import std.algorithm.searching : find;
        auto hit = _pairs.find!((x) => x.key == key)();
    }
    private Pair[] _pairs;
    private struct Pair {
        string key;
        Service service;
    }
}

struct Pair will have an inout(inout) copy constructor defined the following way:

this(inout ref return scope typeof(this) rhs) inout
{
    key = rhs.key;
    service = rhs.service;
}

service = rhs.service will be rewritten to service.__cpctor(rhs.service), but since Service does not define an inout copy constructor it will fail to typecheck and the compiler will annotate it with @disable. Therefore, Pair will become uncopyable. This will result in isInputRange failing on Pair[] (more specifically, this constraints from isInputRange: is(typeof((return ref R r) => r.front)). If the copy constructor of Service is inout(inout), the generated copy constructor of Pair will be succesfully typechecked and everything will work.

For more context, please see this issue [1] and more specifically, this comment [2].

Cheers,
RazvanN

[1] https://issues.dlang.org/show_bug.cgi?id=20876
[2] https://issues.dlang.org/show_bug.cgi?id=20876#c4