December 04, 2014
>
> "There can be at most one owner for any piece of data."
>
> This doesn't seem right. For GC data, the GC owns the data, that is true. But for Ref-counted data, there is more than one owner, and only when all the owners disown the data can it be destroyed.
>
> I think there is a disconnect here, you can't say *nobody* owns the data, and if you say one variable owns the data, which one is it?
>
> Continuing to read...
>
> -Steve

It is in line with this definition

> A variable owns the data it contains if, when the lifetime of the variable is ended, the data can be destroyed.

and the definiton of the lifetime of a variable

> The lifetime of variables is based purely on their lexical scope and order of declaration. The following rules define a hierarchy of lifetimes:

A variable's lifetime starts at the point of its declaration, and ends with the lexical scope it is defined in.
An (rvalue) expression's lifetime is temporary; it lives till the end of the statement that it appears in.
The lifetime of A is higher than that of B, if A appears in a higher scope than B, or if both appear in the same scope, but A comes lexically before B. This matches the order of destruction of local variables.
The lifetime of a function parameter is higher than that of that function's local variables, but lower than any variables in higher scopes.

Because the lifetimes of any two variables are different by this definition and the definition of ownership links to variable lifetime, only one variable can own the data.

So if you have multiple ref-counted slices to an array, no one owns the array until the ref-count goes down to 1. Question remains, if this is a definition of ownership we want to employ.





> There can be at most one owner for any piece of data.
December 04, 2014
int* bar(scope int*);
scope int* foo();

bar(foo());           // Ok, lifetime(foo()) > lifetime(bar())

I'm trying to understand how foo can be implemented in any case. It has no scope ints to return, so where does it get the int from?

I don't see where the proposal defines what exactly can be returned via scope.

Another thing I saw early on:

void abc() {
    scope int* a;
    int* b;
    scope ref int* c = a;  // Error, rule 5
    scope ref int* d = b;  // Ok
    int* i = a;            // Ok, scope is inferred for i
    global_ptr = d;        // Error, lifetime(d) < lifetime(global_ptr)
    global_ptr = i;        // Error, lifetime(i) < lifetime(global_ptr)
    int* j;                // Ok, scope is inferred for i
    global_ptr = j;        // Ok, j is not scope
}

Does this mean ref can now be applied to a variable?

I'm not sure what the difference between scope ref and scope is. is d defined as a reference to b, or is d defined as a new variable that is initialized to what b points at (a la C++ &) ?

-Steve
December 04, 2014
On 12/4/14 10:06 AM, Tobias Pankrath wrote:

>
> So if you have multiple ref-counted slices to an array, no one owns the
> array until the ref-count goes down to 1. Question remains, if this is a
> definition of ownership we want to employ.

This is like saying you have multiple owners :) I don't see the reason to avoid that. It's not like you can't define the owners when there are multiple references. Only one of them will end up destroying the variable, but it's not some other entity that will do it, you have a clear definition of who the owners are.

-Steve

December 04, 2014
> void foo(int[2]) {}
> void bar(int[]) {}
> void main() @nogc {
>     foo([1, 2]s);
>     bar([1, 2]s);
> }

Perhaps better:

void foo(int[2]) {}
void bar(scope int[]) {}
void main() @nogc {
    foo([1, 2]s);
    bar([1, 2]s);
}

Bye,
bearophile
December 04, 2014
On Thu, Dec 04, 2014 at 01:57:43AM -0800, Walter Bright via Digitalmars-d wrote:
> On 12/4/2014 1:53 AM, ketmar via Digitalmars-d wrote:
> >cosmetic issue: some comments are referring to rules by number ("Error, rule 5"), yet the rules aren't explicitly numbered. not a big deal, but still somewhat hard to follow.
> 
> Yeah, still learning wiki markup!

I don't understand the line where rule 5 was invoked:

	scope int* a;
	...
	scope int** f = &a;    // Error, rule 5

Why is it an error, since f has a shorter lifetime than a? And what has it gotta do with rule 5, which currently reads:

	A scope ref variable can be initialized with another scope ref
	variable - scope ref is idempotent.

?


T

-- 
Real men don't take backups. They put their source on a public FTP-server and let the world mirror it. -- Linus Torvalds
December 04, 2014
On Thu, Dec 04, 2014 at 10:31:07AM -0800, H. S. Teoh via Digitalmars-d wrote:
> On Thu, Dec 04, 2014 at 01:57:43AM -0800, Walter Bright via Digitalmars-d wrote:
> > On 12/4/2014 1:53 AM, ketmar via Digitalmars-d wrote:
> > >cosmetic issue: some comments are referring to rules by number ("Error, rule 5"), yet the rules aren't explicitly numbered. not a big deal, but still somewhat hard to follow.
> > 
> > Yeah, still learning wiki markup!
> 
> I don't understand the line where rule 5 was invoked:
> 
> 	scope int* a;
> 	...
> 	scope int** f = &a;    // Error, rule 5
> 
> Why is it an error, since f has a shorter lifetime than a? And what has it gotta do with rule 5, which currently reads:
> 
> 	A scope ref variable can be initialized with another scope ref
> 	variable - scope ref is idempotent.
> 
> ?
[...]

Ah, nevermind, it should be rule 4, not rule 5. Rule 4 states that the address of scope variables cannot be assigned to another scope variable. Please fix the comment. ;-)


T

-- 
I've been around long enough to have seen an endless parade of magic new techniques du jour, most of which purport to remove the necessity of thought about your programming problem.  In the end they wind up contributing one or two pieces to the collective wisdom, and fade away in the rearview mirror. -- Walter Bright
December 04, 2014
On Thu, Dec 04, 2014 at 01:49:06PM +0000, Tobias Pankrath via Digitalmars-d wrote:
> >
> >How would this be handled in the current proposal?
> >
> >class C
> >{
> >  int bar(ref T); // <-- inferred to be scope
> >}
> >
> >class D : C
> >{
> >  override int bar(ref T); // <-- inferred to be NOT scope (but cannot
> >remove scope when overriding)
> >}
> 
> Attribute inference only works for function literals and template functions.  So no inference is done for both methods. Template methods can not be overwritten.

However, AFAIK, template *classes* trigger attribute inference on its (non-template) member functions, so this would be problematic:

	class Base(T) {
		T data;
		void method(ref T); // inferred to be scope
	}

	class Derived : Base!int {
		override void method(ref T); // oops, cannot override
	}


T

-- 
I think Debian's doing something wrong, `apt-get install pesticide', doesn't seem to remove the bugs on my system! -- Mike Dresser
December 04, 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-@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
December 04, 2014
On 12/4/2014 3:21 AM, "Marc Schütz" <schuetzm@gmx.net>" wrote:
>> Errors for scope violations are only reported in @safe code.
>
> Why? If I've explicitly designated a reference as scope, why should it be
> ignored in un-@safe code?

To interface to code that presents a safe interface, but does things under the hood that can't be verified.
December 04, 2014
On 12/4/2014 10:34 AM, H. S. Teoh via Digitalmars-d wrote:
> Please fix the comment. ;-)

done