DIP69 - Implement scope for escape proof references

Walter Bright via Digitalmars-d digitalmars-d at puremagic.com
Thu Dec 4 15:26:32 PST 2014


On 12/4/2014 1:52 PM, H. S. Teoh via Digitalmars-d wrote:
> On Thu, Dec 04, 2014 at 01:10:31PM -0800, Walter Bright via Digitalmars-d wrote:
>> On 12/4/2014 11:41 AM, H. S. Teoh via Digitalmars-d wrote:
>>> Can we pretty please use the term "type qualifier" instead of "type
>>> constructor"? ;-)
>>
>> I think "type constructor" is the more pedantically correct term, but
>> you'll have to ask Andrei :-)
>
> Recently there was a bug filed by Andrei himself, and a bunch of merged
> PRs, that renamed "type constructor" to "type qualifier". The general
> sense I got was that we're deprecating "type constructor" in preference
> for "type qualifier".

Looks like Andrei Hath Spaketh!


>> Because there are inevitably cases where you'll need to wrap unsafe
>> code with a safe interface. By screwing this down too tightly for
>> @system code, you'll force people to use really ugly workarounds.
> 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.

> 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:


> There are, though probably incomplete, and there's also an ongoing
> stream of Phobos PR's for marking things @safe that ought not to be
> @system.  There's a *lot* of Phobos code that needs to be cleaned up in
> this way before this can be workable. (Unless we abuse @trusted as a
> temporary workaround -- but that's not an approach I'd like to
> recommend!)

As long as there's ongoing progress!


> Still not sure how it would address the RC folks' request for compiler
> support, but I suppose that's a different topic.

Yup, different issue.


> I think it's a fairly important issue, since making this work correctly
> will also open up optimization opportunities for a good chunk of
> delegate-based code.

See my other reply with resolution.


> I was thinking more of what implications may hold in the loop body for
> references to (local) variables outside the loop, since that presents
> another potential optimization opportunity if we do it right.

Yes. I think there are a number of optimization properties we can exploit over time.


>> Overloaded operators are treated like calls to the functions that back
>> them.
> OK. You might want to state this explicitly in the DIP, just so it isn't
> left up to interpretation. :-)

Ok.

>>> Finally, the following isn't directly related to this DIP, since
>>> scope is intended to solve this problem, but I thought I should bring
>>> it up.  :-) In the section "escaping via return", 5 points are listed
>>> as sufficient for detecting the "return func(t);" case. The following
>>> section "scope ref" states that these 5 points are "correct" (in
>>> implementing escaping reference detection). However, isn't the
>>> following a loophole?
>>>
>>> 	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().


> 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'.



More information about the Digitalmars-d mailing list