RFC: scope and borrowing

Ivan Timokhin via Digitalmars-d digitalmars-d at puremagic.com
Fri Oct 3 12:05:24 PDT 2014


29.09.2014 18:17, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm at gmx.net>" пишет:
> * What is ElementType!(ByLineImpl!(char, "\n")) in the example from the
> wiki page [1]?

OK, I think I have an idea, but it's not overly elegant.

First of all, I would like to note that the same issue exists with, for 
example, findSubstring function (from "scope with owners" section), 
which does not have a definite return type (so it's unclear what 
ReturnType!findSubstring should be).

Now, an idea that I have is that bare scope should be just a syntactic 
sugar for self-owned scope; i.e., `scope(int*) x;` would be just a short 
way of writing `scope!x(int*) x;`. This would imply that every scoped 
variable has its own unique type, which is probably not that terrible, 
considering that they can't be assigned freely to each other either way. 
This is also somewhat more natural, because it means that there is no 
such thing as just "scoped" variable, it is always connected to a 
particular lifetime.

Then, the following:
---
	string findSubstring(scope(string) haystack,
		             scope(string) needle)
---
would be equivalent to
---
	string findSubstring(scope!haystack(string) haystack,
		             scope!needle(string) needle)
---
so each argument is self-owned and all ownership information is lost 
(but function is still callable with scoped arguments, because scope 
narrowing is allowed).

To preserve ownership information, which is encoded in an arguments' 
types, template is needed:
---
	scope!haystackOwner(string)
	findSubstring(alias haystackOwner)
		            (scope!haystackOwner(string) haystack,
		             scope(string) needle)
---
So, findSubstring *still* doesn't have a definite return type, but now 
it's because it is a function template, not a function.

As for passing unscoped strings to findSubstring, I see two alternatives:
1) Declare that all unscoped references are implicitly convertible to 
scope!GC or something like that (and this conversion is used in such 
cases). This one is probably better.
2) Require a separate overload for an unscoped string.

Now, to address ElementType problem, I would like to reconsider `this` 
lifetime. Since
---
	struct S {
		void f() {}
	}
---
is more or less equivalent to
---
	// not a valid D code
	struct S {}
	void f(ref S this) {}
---
(not strictly equivalent, of course, but the general idea is like that),
`this` inside a method body would behave like a ref parameter and have 
approximately the same lifetime as normal parameters.

Then this code:
---
	@property scope!(const this)(Char[]) front() const
---
would become illegal, since the return value is declared as having 
function-local scope. However, this code:
---
	@property scope!(const this)(Char[])
		front(alias thisOwner)() const scope!thisOwner
---
would work just fine, because it explicitly propagates current object's 
scope (the return type seems the same, but `this` itself now has a 
different type). The downside is that `front` is now callable only for 
scoped variables (it seems inappropriate to convert structs to scope!GC).

Now, ByLineImpl!(char, "\n") wouldn't be an input range, because front 
would not be defined in an unscoped case, and `scope ByLineImpl!(char, 
"\n")` is not a type (because bare scope would be purely a syntactic 
sugar in declarations), so not a range.

However, with this declaration:
---
	scope(ByLineImpl!(char, "\n")) x = ...;
---
typeof(x) would be scope!x(ByLineImpl!(char, "\n")), and 
ElementType!(typeof(x)) would be scope!(const x)(char[]).

As I have said in the beginning, not too elegant, but I think it may 
work. As a bonus, this is a little bit more straightforward and requires 
less special-casing from the compiler side: has only one scope type 
instead of two and no magic tricks with scoped return values. The only 
problems that I can see right away are that the code now is a little 
verbose, and that 'front' is restricted to scoped variables in a new 
version.

Any thoughts?


More information about the Digitalmars-d mailing list