On Wednesday, 21 March 2018 at 17:13:40 UTC, Jack Stouffer wrote:
Consider this example simplified from this PR
https://github.com/dlang/phobos/pull/6281
------
struct GetoptResult
{
Option[] options;
}
struct Option
{
string optShort;
string help;
}
GetoptResult getopt(T...)(scope T opts) @safe
{
GetoptResult res;
auto o = Option(opts[0], opts[1]);
res.options ~= o;
return res;
}
void main() @safe
{
bool arg;
getopt("arg", "info", &arg);
}
------
$ dmd -dip1000 -run main.d
------
main.d(16): Error: scope variable o assigned to non-scope res
main.d(23): Error: template instance `onlineapp.getopt!(string,
string, bool*)` error instantiating
------
The only way I've found to make the code compile and retain the
pre-dip1000 behavior is to change the Option construction to
------
auto o = Option(opts[0].idup, opts[1].idup);
------
How can we return non-scoped result variables constructed from
scope variables without copies?
I thought that maybe adding a function to Option and marking it
as `scope` would work:
struct GetoptResult
{
Option[] options;
void addOptions(scope Option opt) @safe scope
{
//Error: scope variable opt assigned to non-scope this
options ~= opt;
}
}
But the compiler doesn't like that. However, I _did_ get it
working by doing this:
GetoptResult getopt(T...)(scope T opts) @safe
{
return GetoptResult([Option(opts[0], opts[1])]);
}
Which is not ideal, obviously, but the notion that some code has
to be rewritten to accomodate ownership semantics is not a new
one; one of the major complaints I've seen about Rust is that it
requires you to adjust your coding style to satisfy the borrow
checker.