return scope ref outlives the scope of the argument

Eugene Wissner belka at caraus.de
Tue Jun 25 12:32:35 UTC 2019


On Tuesday, 25 June 2019 at 12:04:27 UTC, Jonathan M Davis wrote:
> On Tuesday, June 25, 2019 1:32:58 AM MDT Eugene Wissner via 
> Digitalmars-d- learn wrote:
>> struct Container
>> {
>> }
>>
>> static struct Inserter
>> {
>>      private Container* container;
>>
>>      private this(return scope ref Container container) 
>> @trusted
>>      {
>>          this.container = &container;
>>      }
>>
>> }
>>
>> auto func()()
>> {
>>      Container container;
>>      return Inserter(container);
>> }
>>
>> void main()
>> {
>>      static assert(!is(typeof(func!())));
>> }
>>
>> The code above compiles with dmd 2.085, but not 2.086 (with
>> -preview=dip1000). What am I doing wrong?
>
> Okay. I clearly looked over what you posted too quickly and 
> assumed that the subject was the error that you were actually 
> getting. The @trusted there is what's making the static 
> asertion fail.
>
> Inserter is able to compile with -dip1000 (or 
> -preview=dip1000), because you marked it as @trusted, which 
> throws away the scope checks. If you mark it @safe, it won't 
> compile. Without -dip1000, I wouldn't have expected anything to 
> be caught, but trying it on run.dlang.io, it looks like the 
> return probably makes it fail, which I find surprising, since I 
> didn't think that return had any effect without -dip25, but I 
> haven't done much with return on parameters.
>
> You'd have an easier time figuring out what's going on if you'd 
> just not make func a template rather than use the static 
> assertion, because then you'd see the compiler errors.
>
> In any case, by using @trusted, you're getting around the scope 
> compiler checks, which is why Inserter is able to compile with 
> -dip1000. Without -dip1000, I'm not experience enough with 
> return parameters to know what the compiler will or won't 
> catch, but the code is an @safety probelm regardless. It does 
> look like the behavior changed with 2.086 even without -dip1000 
> being used, which probably has something to do with how the 
> compiler was changed for DIP 1000, though it probably wasn't on 
> purpose, since in theory, the behavior shouldn't have changed 
> without -dip1000, but I don't know.
>
> - Jonathan M Davis

Yes, reduced code could be a bit better.

@trusted doesn't throw scope checks away (and it wouldn't make 
any sense since I don't see another way to make the code above 
safe). Try:

struct Container
{
}

private Container* stuff(return scope ref Container container) 
@trusted
{
     return &container;
}

auto func()
{
     Container container;
     return stuff(container);
}

It fails with -dip1000 and works without (as expected).

"return scope ref" parameter in the constructor means, that the 
constructed object has the same scope as the scope of the 
argument.

I just want to know whether the behaviour of 2.085 or 2.086 is 
correct and if it is an "improvement" in 2.086, what I'm doing 
wrong.


More information about the Digitalmars-d-learn mailing list