RFC: scope and borrowing

via Digitalmars-d digitalmars-d at puremagic.com
Wed Aug 27 12:32:23 PDT 2014


On Tuesday, 26 August 2014 at 22:53:30 UTC, Marco Leise wrote:
> You could try to formalize some error messages and how the
> compiler's reasoning would go. What happens when I pass
> identifiers to scope!(…) return types?
> - Can the compiler look up the identifiers' types and scopes
>   in all cases?

It has to be able to. If a non-visible identifier is specified, 
it is an error.

> - Will the compiler deduce the return type from these
>   identifiers? E.g. "scope!(someString) ref getString();" will
>   work like in your example? I don't think so, because the
>   "lifetime identifiers" could be structs containing the
>   returned type.

I see, this was a stupid mistake. Of course this function needs 
to specify the full type, as no type deduction can happen when 
the body isn't available. Fixed in on the Wiki.

> - What if we used incompatible types like
>   "scope!(someString, someIntPtr)" there?
> - What about variables?
>

Just to be sure: You can only specify variables as owners, not 
types. I've clarified this on the Wiki.

>   static int someInt = 32;
>   string someString;
>   scope!(someString, someInt) int* x;
>   x = &someInt;
>
>   Is the declaration of x in error? Strings don't contain
>   integers unless unsafe casts are used, so why would they
>   narrow the lifetime of an integer reference?

This is an interesting thought... But I would still allow this 
for a different reason. At the beginning, I only thought about 
`scope` as a tool for memory management, but I believe it can be 
applied for lifetime management of arbitrary resources. Let's 
slightly modify your example, and use different types:

     Task someProcess;
     scope!someProcess HANDLE my_handle;

`someProcess` could represent an external process that is managed 
by this program, and `my_handle` could refer to some kind of 
object in this external process. This handle is only valid as 
long as the process exists, even though it is not a memory 
reference, and `Task` might not contain any members of type 
`HANDLE`. (This is not an ideal example, of course, because the 
process could terminate for reasons outside of our control.) A 
similar example would be a connection to the X server, and a 
handle to an object allocated from it.

I already wrote this idea into the section "scope for 
non-reference types", with a simpler example. In fact, I believe 
that the entire proposal will be a bit simpler if 
references/pointers aren't treated specially.

>
> - Is it necessary to keep around all declared lifetime
>   identifiers? In the snippet above (assuming it is valid), it
>   looks like the shorter lived `someString' is enough to
>   establish the semantics.

Yes, it's possible to some degree, see the section 
"Considerations for the implementation". Unfortunately, this 
doesn't work with function declarations, and is incompatible with 
the suggested `scope!(const ...)` extension.


More information about the Digitalmars-d mailing list