November 05, 2022

Apparently there a difference between:

  • Message withBody(Body body_) return scope { /* … */ }
    
  • Message withBody(Body body_) scope return {  /* … */ }
    
>
Deprecation: returning `this._body` escapes a reference to parameter `this`
       perhaps change the `return scope` into `scope return`

What is it?
And why (…does the order of attributes matter)?

November 05, 2022

On Saturday, 5 November 2022 at 16:13:18 UTC, 0xEAB wrote:

>

Apparently there a difference between:

  • Message withBody(Body body_) return scope { /* … */ }
    
  • Message withBody(Body body_) scope return {  /* … */ }
    
>
Deprecation: returning `this._body` escapes a reference to parameter `this`
       perhaps change the `return scope` into `scope return`

What is it?
And why (…does the order of attributes matter)?

Basically, the return attribute is a modifier, and has no meaning on its own. Either it modifies ref to create return ref, or it modifies scope to create return scope. (In the case of a struct method, like in your example, the ref is implicit.)

In the past, if you used all 3 of ref, scope, and return on a single parameter, it was ambiguous whether the return was modifying ref or scope. This lead to a lot of confusion and frustration (see this thread for the gory details).

To resolve the ambiguity, Walter decided to make the order of the keywords significant: if you write return scope, in exactly that order, then return modifies scope; otherwise, it modifies ref.

I believe that the plan is to eventually require return ref to be written in exactly that order as well (see Walter's reply in this thread), but that's a breaking change, and will require a deprecation period. So in the meantime, we have kind of an awkward half-solution, where keyword order is significant for return scope but not for return ref.