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