Difference between revisions of "DIP36"

From D Wiki
Jump to: navigation, search
(Created page with "{| class="wikitable" !Title: !'''rvalue references''' |- |DIP: |36 |- |Version: |1 |- |Status: |Work in progress |- |Created: |2013-04-08 |- |Last Modified: |2013-04-08 |- |...")
 
(Corrected mistake about "ref" semantics)
Line 1: Line 1:
{| class="wikitable"
+
{|class="wikitable"
 
!Title:
 
!Title:
 
!'''rvalue references'''
 
!'''rvalue references'''
Line 20: Line 20:
 
|Author:
 
|Author:
 
|Randy Schütt, Михаил Страшун
 
|Randy Schütt, Михаил Страшун
|-
+
|-}
}
 
  
 
== Abstract ==
 
== Abstract ==
This DIP describes issues with current usage of various rvalues as a function parameters and proproses possible improvement - formalization of scope references. As a positive side effect, intentions of <code>scope</code> qualifier are better defined into formal restrictions.
+
This DIP describes issues with current usage of various rvalues as a function parameters and proproses possible improvement - formalization of scope references. As a positive side effect, intentions of <code>scope</code> qualifier are better defined into formal restrictions. Minor redefinition of <code>ref</code> in regards to <code>@safe</code> is also proposed.
  
 
== Rationale ==
 
== Rationale ==
Line 56: Line 55:
 
== Description ==
 
== Description ==
 
=== Core porposal ===
 
=== Core porposal ===
1) <code>ref</code> is allowed to handle rvalues with valid address now. <code>ref</code> does not pretend to be <code>safe</code>.
+
1) <code>scope ref</code> is similar to <code>ref</code> but may be allowed in <code>@safe</code> code as it is prohibited to escape or store scoped reference, as well as taking its address. It is allowed to accept rvalues.
2) <code>scope ref</code> is defined as <code>ref</code> but may be allowed in <code>@safe</code> code as it isbe prohibited to escape or store scoped reference, as well as taking its address.
+
2) <code>const scope ref</code> (or <code>in ref</code> is like <code>scope ref</code> but prohibits mutation. It imposes usage restrictions (can't modify, can't store reference, can't take address) than make working with them indistinguishable from working with value types. Compiler can abuse it to create temporary variables for trivial type literals and pass references to them instead - it can't possibly change function semantics.
3) <code>const scope ref</code> (or <code>in ref</code> is like <code>scope ref</code> but prohibits mutation. It imposes usage restrictions (can't modify, can't store reference, can't take address) than make working with them indistinguishable from working with value types. Compiler can abuse it to create temporary variables for trivial type literals and pass references to them instead - it can't possibly change function semantics.
 
  
 
==== Example ====
 
==== Example ====
Line 86: Line 84:
 
}
 
}
  
// Now allows some rvalues, does not pretend to be @safe
+
// Does not pretend to be @safe any more
 
void test2(ref A a) {
 
void test2(ref A a) {
 
}
 
}
Line 102: Line 100:
 
     A a = A(23); // no difference
 
     A a = A(23); // no difference
 
     test1(a);
 
     test1(a);
     test2(A(1337)); // not @safe, test2 can leak reference to temporary
+
     test2(A(1337)); // Prohibited, plain "ref" can't accept rvalues
     test2(a); // not @safe, unless it can be verified that a is allocated on heap in GC memory. Same reasons.
+
     test2(a); // fine, but not @safe, unless it can be verified that a is allocated on heap in GC memory
 
     test3(1337); // Fine and @safe. Temporary int variable with value 1337 is created.
 
     test3(1337); // Fine and @safe. Temporary int variable with value 1337 is created.
 
     test3(a.id); // Same but no temporary is needed.
 
     test3(a.id); // Same but no temporary is needed.
Line 114: Line 112:
  
 
=== Formal definition of scope ref semantics ===
 
=== Formal definition of scope ref semantics ===
 +
 +
=== @safe concerns ===
  
 
=== Backwards compatibility ===
 
=== Backwards compatibility ===

Revision as of 08:49, 9 April 2013

Abstract

This DIP describes issues with current usage of various rvalues as a function parameters and proproses possible improvement - formalization of scope references. As a positive side effect, intentions of scope qualifier are better defined into formal restrictions. Minor redefinition of ref in regards to @safe is also proposed.

Rationale

There is a quite common necessity to pass some data as a function argument without both copying and caring about its referrability. Currently D provides no means to do it properly. ref T can't be used on with rvalue literals. T results in (possibly) costly value copying for aggregate rvalues. auto ref T is template-based and thus bloats at least the symbol table. Solutions is needed that will be simple, provide some guarantees and avoid extra bloat.

void main()
{
    // Only signature for func1 to accept both is func1(int), which is acceptable for trivial types
    int x;
    func1(x);
    func1(42);

    // For aggregate types passing by reference may be desired for both performance and avoiding side-effects of non-trivial constructors.
    // func2(ref Aggr) will accept both. This approach won't work for int literal though as it is not adressable
    struct Aggr { }
    Aggr s;
    func2(s);
    func2(Aggr());

    // Now the question is, how can I say "I want to process this data with no side-effects, won't mutate it and don't care if is adressable"?
    // func3(T)(auto ref T) is current solution but it works by adding extra template instantiation for each two cases. This is both not needed
    // and does not scale with argument count.
}

Discussion threads:

Description

Core porposal

1) scope ref is similar to ref but may be allowed in @safe code as it is prohibited to escape or store scoped reference, as well as taking its address. It is allowed to accept rvalues. 2) const scope ref (or in ref is like scope ref but prohibits mutation. It imposes usage restrictions (can't modify, can't store reference, can't take address) than make working with them indistinguishable from working with value types. Compiler can abuse it to create temporary variables for trivial type literals and pass references to them instead - it can't possibly change function semantics.

Example

import std.stdio;

struct A {
public:
	int id;

	this(int id) {
		this.id = id;
	}

	this(this) {
		writeln("A Postblit for ", this.id);
	}
}

// Like a normal ref A, but a bit more restrictive.
void test1(scope ref A a) {
        // static A* global_state = &a; // prohibited, see explanations later
}

// Almost nothing can be done with parameter, only value-style read access.
void test12(in ref A a) {
}

// Does not pretend to be @safe any more
void test2(ref A a) {
}

// Similar to "auto ref" but no extra template instantations. Compiler creates temporaries for rvalues that have no address on caller site.
void test3(T)(in ref T id) {
}

// Consistent with test1. Only adressable parameters are valid, not temporaries, no extra template instances.
void test32(T)(scope ref T id) {
}

void main() {
    test1(A(42)); // @safe, this temporary value is valid for mutation and "scope" ensures it does not leak scope
    A a = A(23); // no difference
    test1(a);
    test2(A(1337)); // Prohibited, plain "ref" can't accept rvalues
    test2(a); // fine, but not @safe, unless it can be verified that a is allocated on heap in GC memory
    test3(1337); // Fine and @safe. Temporary int variable with value 1337 is created.
    test3(a.id); // Same but no temporary is needed.
    test32(1337); // Prohibited, no address for "1337"
    test32(a.id); // fine and @safe
}

Definition of "scope" qualifier for ref types

Formal definition of scope ref semantics

@safe concerns

Backwards compatibility

Interconnecton with DIP25

Other proposed solutions

Copyright

This document has been placed in the Public Domain.

Title: rvalue references
DIP: 36
Version: 1
Status: Work in progress
Created: 2013-04-08
Last Modified: 2013-04-08
Author: Randy Schütt, Михаил Страшун