On Friday, 12 December 2014 at 08:42:22 UTC, Manu via Digitalmars-d wrote:
On 11 December 2014 at 23:55, via Digitalmars-d
<[email protected]> wrote:
This is a point that most people don't seem to understand yet, and which
wasn't obvious for me either, at the beginning:

* A `ref` parameter means that it cannot escape the function, _except_ by
return.
* A `scope ref` parameter means that it cannot escape the function _ever_,
not even by return.
* A `scope ref` return means that it cannot leave the current statement.

Therefore, a `scope ref` return value can be passed on to the next function as a `ref` argument. If that function again returns a reference (even if not explicitly designated as `scope`), the compiler will treat it as if it were
`scope ref`.

Ummm. I reckon there's a good reason that people don't seem to
understand this... because it would have difficulty being any more
unintuitive!
It's contrary to the behaviour of basically everything else in D! const, pure, nothrow, etc... they all work a reliable and consistent way.

Unfortunately I have to agree.


Also, I still don't think I get it... a scope-ref return, which has a restriction as you say, can be subverted by being piped through a
function that receives and returns it as ref?
What is the point?

It cannot be subverted. As soon as you pass something into a function G() as `ref` that's been returned from a function F() via `scope ref`, the compiler needs to treat what is returned from G() as `scope ref`, even if it's only declared as `ref`.

As you say, it's unintuitive and non-obvious.


I'm also quite uneasy with the fact that scope would not be transitive as a storage class. What happens when it's applied to a value type, like a struct, that contains some pointers? An adaptation wrapper for a single pointer is super common; ie, a tiny struct passed by value with scope needs to have it's contained pointer receive the scope-ness
of the argument.


I agree, this is important. In my proposal, this works without transitivity. The wrapper stores the pointer as a `scope` member, then by copying the wrapper, the pointer gets copied implicitly, to which the normal scope restrictions apply (`scope` on members means "will not outlive the aggregate"). If it stored it as normal non-scope pointer, it couldn't get assigned in the first place. (Additionally, some higher level tricks are possible if we allow scope for value types and overloading on scope.)

How can a member be marked scope? Apparently it's a storage class, not
a type constructor... we can only attribute storage classes to
function args/results(?).

I was talking about my proposal here, where it's a type modifier, not a storage class.

deadalnix also brought up the problem of transitivity. This, too, would simply go away if it's a type modifier.

Reply via email to