DIP69 - Implement scope for escape proof references

H. S. Teoh via Digitalmars-d digitalmars-d at puremagic.com
Thu Dec 4 11:41:34 PST 2014


On Thu, Dec 04, 2014 at 01:24:13AM -0800, Walter Bright via Digitalmars-d wrote:
> http://wiki.dlang.org/DIP69
> 
> Despite its length, this is a fairly simple proposal. It adds the
> missing semantics for the 'scope' storage class in order to make it
> possible to pass a reference to a function without it being possible
> for it to escape.

Finally! Thanks for the hard work, looking forward for this to be
implemented (in some shape of form -- see comments below).


> This, among other things, makes a ref counting type practical. It also
> makes it more practical to use other storage allocation schemes than
> garbage collection.
> 
> It does not make scope into a type constructor, nor a general
> type-annotation system.
[...]

Can we pretty please use the term "type qualifier" instead of "type
constructor"? ;-)

Anyway, here are a few comments:

1) Why are scope violations only reported for @safe code?? IMO this
greatly limits the usefulness of this DIP.  If I mark something as
scope, I'd expect it should be enforced by the compiler regardless of
@safe annotations, otherwise what's the point??

Currently, due to the incompleteness of @safe, it's difficult to use
@safe annotations everywhere I'd like to (e.g. I need to use some
un- at safe Phobos functions that really ought to be @safe, but aren't due
to various reasons, like compiler limitations, etc.). This greatly
limits the usefulness of this DIP, if scope is only enforced in @safe
code!


2) Is there a way to detect if something is marked as scope? If not, how
does this proposal actually enable ref-counted types? (I'm assuming a
library ref-counting type here; or are we expecting further compiler
enhancements for ref counting?)


3) What does scope mean for delegate parameters? To what does the scope
apply, the delegate itself, its body, or its return value, or ...?

	struct S {
		void opApply(scope void delegate(ref int) loopBody) {
			...
			// what restrictions (might) apply here w.r.t.
			// how loopBody can be called?
		}
	}

And what would be the effect on the caller's side?

	S s;
	foreach (i; s) {
		// what restrictions (might) apply here?
	}


4) Under "Expressions", how does scope interact with overloaded
operators? Do the same rules apply to expressions that use overloaded
operators as they apply to built-in operators, or do they apply as
though the overloaded operators were written out in function-call
syntax?  What happens if some overloaded operators take a mix of scope
and non-scope parameters?


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. (In fact, dmd happily accepts
this code, even if everything is annotated with @safe.) Note that the
escaping reference to x can be arbitrarily deeply nested inside S, so
it's non-trivial to decide whether there's no possibility for references
to (parts of) S to leak from func().


T

-- 
If I were two-faced, would I be wearing this one? -- Abraham Lincoln


More information about the Digitalmars-d mailing list