DIP 1016--ref T accepts r-values--Formal Assessment

Manu turkeyman at gmail.com
Sat Jan 26 02:14:56 UTC 2019


On Fri, Jan 25, 2019 at 4:20 PM Neia Neutuladh via
Digitalmars-d-announce <digitalmars-d-announce at puremagic.com> wrote:
>
> On Fri, 25 Jan 2019 23:08:52 +0000, kinke wrote:
>
> > On Friday, 25 January 2019 at 19:08:55 UTC, Walter Bright wrote:
> >> On 1/25/2019 2:57 AM, kinke wrote:
> >>> On Thursday, 24 January 2019 at 23:59:30 UTC, Walter Bright wrote:
> >>>> On 1/24/2019 1:03 PM, kinke wrote:
> >>>>> (bool __gate = false;) , ((A __pfx = a();)) , ((B __pfy =
> >>>>> b();)) , __gate = true , f(__pfx, __pfy);
> >>>>
> >>>> There must be an individual gate for each of __pfx and pfy.
> >>>> With the rewrite above, if b() throws then _pfx won't be destructed.
> >>>
> >>> There is no individual gate, there's just one to rule the
> >>> caller-destruction of all temporaries.
> >>
> >> What happens, then, when b() throws?
> >
> > `__pfx` goes out of scope, and is dtor expression (cleanup/finally) is
> > run as part of stack unwinding. Rewritten as block statement:
>
> And nested calls are serialized as you'd expect:
>
> int foo(ref S i, ref S j);
> S bar(ref S i, ref S j);
> S someRvalue(int i);
>
> foo(
>     bar(someRvalue(1), someRvalue(2)),
>     someRvalue(4));
>
> // translates to something like:
> {
>     bool __gate1 = false;
>     S __tmp1 = void;
>     S __tmp2 = void;
>     S __tmp3 = void;
>     __tmp1 = someRvalue(1);
>     try
>     {
>         __tmp2 = someRvalue(2);
>         __gate1 = true;
>         __tmp3 = bar(__tmp1, __tmp2);
>     }
>     finally
>     {
>         if (!__gate1) __tmp1.__xdtor();
>     }
>     S __tmp4 = void;
>     bool __gate2 = false;
>     try
>     {
>         __tmp4 = someRvalue(4);
>         __gate2 = true;
>         return foo(__tmp3, __tmp4);
>     }
>     finally
>     {
>         if (!__gate2)
>         {
>             __tmp3.__xdtor();
>         }
>     }
> }

Is this fine?

Given above example:

int foo(ref S i, ref S j);
S bar(ref S i, ref S j);
S someRvalue(int i);

foo(
    bar(someRvalue(1), someRvalue(2)),
    someRvalue(4));

===>

{
  S __tmp0 = someRvalue(1);
  S __tmp1 = someRvalue(2);
  S __tmp2 = bar(__tmp0, __tmp1);
  S __tmp3 = someRvalue(4);
  foo(__tmp2, __tmp3);
}

Removing the `void` stuff end expanding such that the declaration +
initialisation is at the appropriate moments; any function can throw
normally, and the unwind works naturally?


More information about the Digitalmars-d-announce mailing list