Thread overview
inout auto ref escaping a reference to parameter, only errors with vibe Json type, or if inout is there.
Mar 11, 2019
aliak
Mar 12, 2019
aliak
Mar 12, 2019
aliak
March 11, 2019
Hi,

I have an error that says "Error: returning `match1(opt)` escapes a reference to parameter `opt`, perhaps annotate with `return`".

The code is here: https://run.dlang.io/is/ESZDW4 (It's copied at the end of this post as well)

1) If you remove the inout from line 11. It works.
2) If you *do not* call match2 and call match1 instead, it also works.
3) If you return something other than vibe's Json type, it works (afaict)

Am I using inout wrong? Why is it only happen with Json type so far. If I return any other random struct it works fine. And why does it work if I don't go through the "match2" template? Any help would be much appreciated.

---

template match1(handlers...) {
    auto ref match1(T)(inout auto ref Optional!T opt) { // remove inout, it works
        if (opt.empty) {
            return  handlers[1]();
        } else {
            return  handlers[0](opt.front);
        }
    }
}

template match2(handlers...) {
    auto match2(T)(auto ref Optional!T opt) {
        return match1!handlers(opt);
    }
}

void main() {
    some(1)
        .match2!( // use match1, it works
            (int i) {return Json(1);}, // return anything else, it works
            () {return Json(1);}
        )
        .writeln;
}

Cheers,
- Ali
March 12, 2019
On Monday, 11 March 2019 at 22:29:05 UTC, aliak wrote:
> Hi,
>
> I have an error that says "Error: returning `match1(opt)` escapes a reference to parameter `opt`, perhaps annotate with `return`".
>
> [...]

Ok, I've found out something else. It only happens when you're returning a type that has an indirection. So instead of the Json type if we returned an S type where S was:

struct S {
  void[2] data;
}

We get the same error.

March 12, 2019
On Monday, 11 March 2019 at 22:29:05 UTC, aliak wrote:
> [...]

Here's a much reduces test case:

struct W(T) {}

struct S {
    int* data;
}

template match1(alias handler) {
    auto ref match1(T)(inout auto ref W!T w) {
        return handler();
    }
}

template match2(alias handler) {
    auto match2(T)(auto ref W!T w) {
        return match1!handler(w);
    }
}

void main() {
    W!int()
        .match2!(() => S());
}