DIP69 - Implement scope for escape proof references

H. S. Teoh via Digitalmars-d digitalmars-d at puremagic.com
Thu Dec 4 15:54:22 PST 2014


On Thu, Dec 04, 2014 at 03:26:32PM -0800, Walter Bright via Digitalmars-d wrote:
> On 12/4/2014 1:52 PM, H. S. Teoh via Digitalmars-d wrote:
[...]
> >Are there any use cases for bypassing scope semantics in @system code?
> 
> One is to interface with legacy code that does not use 'scope'
> properly in its declarations. There are probably more.
> 
> >How common are they?
> 
> I don't know.
> 
> >Maybe such code *should* look ugly -- to draw attention to the fact
> >that something un- at safe is going on.
> 
> @system is ugly enough.

Not when all code is @system by default!


> >Or perhaps we can make cast() strip away scope? I much rather require
> >explicit annotation for potentially unsafe operations, than to have
> >subtle bugs creep into the code just because I forgot to mark
> >something as @safe.
> 
> Start your modules with:
> 
>   @safe:

I would, except that Phobos limitations preclude that. Someone else has
already posted the list of bugs, so I won't repeat that here. Needless
to say, it's still a ways off before putting @safe: at the top of your
modules will solve the problem.


[...]
> >>>	struct S {
> >>>		int x;
> >>>	}
> >>>	ref int func(ref S s) {
> >>>		return s.x;
> >>>	}
> >>>	ref T foo() {
> >>>		S s;
> >>>		return func(s); // escaping reference
> >>>	}
> >>>
> >>>Since S cannot implicitly convert to int, it would appear that this
> >>>circumvents escaping reference detection.
> >>
> >>No, because under this proposal, s.x is treated as if it were just s
> >>as far a scope rules are concerned.
> >[...]
> >
> >I'm not quite sure I see how this could be implemented. When the
> >compiler is compiling func(), say it's in a different module, there's
> >nothing about the function that says it's illegal to return a reference
> >to the member of an incoming argument.
> 
> That's right, so the compiler assumes it does, unless the parameter is
> marked as scope.
> 
> >First of all, this isn't a template function so scope inference isn't
> >in effect; secondly, even of it were in effect (say we write it as
> >`func()(ref S s)` instead), it wouldn't be able to infer the return
> >value as scope, since it's obviously escaping a reference to a
> >function argument.
> 
> 'scope ref' parameters cannot be returned by 'ref' or by 'scope ref'.
> The only distinction between 'ref' and 'scope ref' parameters is the
> latter cannot be returned by 'ref' or 'scope ref'.
> 
> >So, unless I'm missing something obvious, func() will be accepted by
> >the compiler (as it should, since we didn't mark anything as scope
> >here).
> 
> The compiler assumes func(s) returns a ref to s, and so it won't allow
> func(s) to be returned from foo().

Ah, I see. So you're saying that under this DIP, `return func(...);`
from a ref function will be prohibited unless the arguments to func()
were all either scope or non-reference?

That sounds good, though it *is* pretty invasive, as any existing ref
functions that do this will need to be revised, which potentially
spreads 'scope' to many other places, depending on how deeply the chain
of tail recursion / tail func calls go.


> >Now when the compiler compiles foo(), it can no longer see what's
> >inside func(), so there's no way for it to know that the ref int
> >being returned actually comes from the ref S parameter.
> 
> It assumes it does, unless 'ref S' is marked 'scope ref S'. It's the
> whole point of 'scope ref'.

Got it, thanks.


T

-- 
Shin: (n.) A device for finding furniture in the dark.


More information about the Digitalmars-d mailing list