Flaw in DIP1000? Returning a Result Struct in DIP1000

Meta jared771 at gmail.com
Wed Mar 21 19:15:41 UTC 2018


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.



More information about the Digitalmars-d mailing list