www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - [SAoC] Move semantics and STL containers

reply Suleyman <sahmi.soulaimane gmail.com> writes:
Hello,

I will be working in this SAoC season on the D bindings to simple 
STL containers project[1].

This thread will be updated weekly with progress status.

The theme of this SAoC project is to improve and consolidate D's 
interoperability through bindings to the C++ STL containers. This 
will involve fixing a number of DMD issues related to C++ 
interop, as well as implementing the move constructor in D.

Milestones:

* 1. Full implementation of rvalue ref.
  - ` rvalue ref` as attribute
  - __traits(isRvalueRef)
  - `__rvalue(T)` as type constructor
  - implement full semantics
  - expand `auto ref` to rvale ref
  - match the C++ mangling for rvalue ref

* 2. Full implementation of the move constructor
  - move constructor
  - move opAssign
  - implement full semantics:
    - default behaviour
    - ` disable`
    - relationship with the copy constructor
    - conflict with existing semantics

* 3. Fix blocking DMD issues and implement std::string and 
std::vector on all platforms
  - Fix issue https://issues.dlang.org/show_bug.cgi?id=20235
  - Investigate and fix the mangling issue which is blocking 
std::pair
  - implement move semantics for std::string
  - implement std::vector for GCC and Clang lib

* 4. Finalize the project
  - Ensure move semantics work properly
  - ensure backwards compatibility
  - implement existing STL containers on all platforms
  - resolve all D blockers

____

[1] https://github.com/dlang-cpp-interop/stl-containers/
Sep 21
next sibling parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
Week 1 status:
     - ` rvalue ref` attribute fully implemented[1]
       - grammar definition[2]
       - parameter and return semantics
       - D and C++ name mangling
       - `cast( rvalue ref)` to convert lvalues to rvalue ref
       - `__traits(isRvalueRef)` for parameters
       - fully functional with ctfe, inliner, optimizer, codgen
       - escape analysis is the same as `ref`

____
[1] https://github.com/dlang/dmd/pull/10426
[2] https://github.com/dlang/dlang.org/pull/2703
Sep 21
parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
Week 2 status:

     - ` rvalue ref` attribute:
         - `auto  rvalue ref` for function parameters expands to 
either `ref` or ` rvalue ref`
         - `auto ref` for function parameters retains its current 
behaviour
         - `auto ref` on function returns infers refness properly 
between `ref`, ` rvalue ref`, and no ref.

     - ` rvalue` or `__rvalue` as a type constructor[1]:
         - grammar definition[2]
         - enable both syntaxes ` rvalue` and `__rvalue`
         - only usable with ref or with pointers
         - ability to cast to or from ` rvalue`
         - implicit conversion to or from ` rvalue` allowed except 
with pointers
         - special behaviour with function calls where rvalue 
arguments are implicitly ` rvalue` while lvalues need an explicit 
cast
         - ` rvalue` ref is overloadable with bare ref
         - recognized as a type specialization with `is(T == 
 rvalue)`
         - D and C++ name mangling
         - works with ctfe, inliner, optimizer, and escape analysis

____
[1] https://github.com/dlang/dmd/pull/10426
[2] https://github.com/dlang/dlang.org/pull/2704
Sep 28
next sibling parent reply Exil <Exil gmall.com> writes:
On Saturday, 28 September 2019 at 11:06:02 UTC, Suleyman wrote:
 [1] https://github.com/dlang/dmd/pull/10426
 [2] https://github.com/dlang/dlang.org/pull/2704
So was rvalue pre-approved or something? Last thing I heard about rvalue references is that they were rejected (along with the DIP) and a new DIP was being written. Was that forgone?
Sep 28
parent reply Manu <turkeyman gmail.com> writes:
On Sat, Sep 28, 2019 at 12:55 PM Exil via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Saturday, 28 September 2019 at 11:06:02 UTC, Suleyman wrote:
 [1] https://github.com/dlang/dmd/pull/10426
 [2] https://github.com/dlang/dlang.org/pull/2704
So was rvalue pre-approved or something? Last thing I heard about rvalue references is that they were rejected (along with the DIP) and a new DIP was being written. Was that forgone?
Completely different and unrelated topic. Passing rvalue temporaries by ref is different than rvalue references. It's not preapproved, this work is optimistic.
Sep 28
next sibling parent reply Johannes Pfau <nospam example.com> writes:
Am Sat, 28 Sep 2019 14:29:35 -0700 schrieb Manu:

 On Sat, Sep 28, 2019 at 12:55 PM Exil via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On Saturday, 28 September 2019 at 11:06:02 UTC, Suleyman wrote:
 [1] https://github.com/dlang/dmd/pull/10426 [2]
 https://github.com/dlang/dlang.org/pull/2704
So was rvalue pre-approved or something? Last thing I heard about rvalue references is that they were rejected (along with the DIP) and a new DIP was being written. Was that forgone?
Completely different and unrelated topic. Passing rvalue temporaries by ref is different than rvalue references. It's not preapproved, this work is optimistic.
But is there some kind of explanation for these changes? There's the spec PR of course, but that does not really explain why / how to use this feature. -- Johannes
Sep 29
parent Suleyman <sahmi.soulaimane gmail.com> writes:
On Sunday, 29 September 2019 at 09:53:09 UTC, Johannes Pfau wrote:
 But is there some kind of explanation for these changes? 
 There's the spec PR of course, but that does not really explain 
 why / how to use this feature.
A short description of each implementation: The rvalue attribute is under the compiler switch `-preview=rvalueattribute`. Usage example: ```d struct S {} void func( rvalue ref S p); rvalue ref S func(); S a; auto b = cast( rvalue ref)a; void gun( rvalue ref S p) { enum r = __traits(isRvalueRef, p); } void func()(auto rvalue ref S p); auto rvalue ref S func(); ``` Semantics are similar to C++ rvalue ref. The C++ ABI and name mangling is matched as well with `extern(C++)` functions. In short summary: * The ` rvalue ref` attribute: - can only be applied to function parameters or function returns. - ` rvalue ref` parameters only receive an rvalue or an "rvalue ref". where an "rvalue ref" is one of: 1. `cast( rvalue ref)` expression. 2. return value of an ` rvalue ref` function. - ` rvalue ref` functions only returns an "rvalue ref". - ` rvalue ref` can be overloaded with `ref`, but not with value parameters. - `cast( rvalue ref)` only applies to lvalues. - `__traits(isRvalueRef)` return `true` for ` rvalue ref` parameters. - The result of `__traits(getAttributes)` when called with a function parameter includes `" rvalue ref"` when applicable. - The result of `__traits(getFunctionAttributes)` includes `" rvalue ref"` when the function returns it. - `auto ref` parameters retain their present semantics, with an additional flavor `auto rvalue ref` which expands to either: 1. `ref` if the argument received is an lvalue. 2. ` rvalue ref` if the argument received is an rvalue. - `auto ref` on function returns infers either: 1. `ref` if the return expression is an lvalue. 2. ` rvalue ref` if return expression is "rvalue ref". 3. value if the return expression is an rvalue. `auto ref` and `auto rvalue ref` are synonymous when applied to function returns since they do not clash with one another unlike the case with parameters. The rvalue type constructor is under the compiler switch `-preview=rvaluetype`. Usage example: ```d struct S {} void func( rvalue ref S p); ref rvalue(S) func(); S a; auto b = cast( rvalue)a; void gun(ref rvalue(S) p) { enum r = is(typeof(p) == rvalue); } const( rvalue(S))* var; void func()(auto ref rvalue(S) p); auto ref rvalue(S) func(); assert(typeid( rvalue(int)).toString() == " rvalue(int)"); static assert(is( rvalue(S) : S)); static assert(!is( rvalue(S)* : S*)); ``` Semantics summary: * The ` rvalue` type constructor: - Two syntaxes are made available ` rvalue` and `__rvalue`, which one of them will be retained is TBR. - Tariables cannot be declared with ` rvalue` types except if declared with `ref` which only applies to functions parameters. But pointers to ` rvalue` types (ex: ` rvalue(T)*`) are allowed for variable declarations. - The element type of arrays and associative arrays cannot be ` rvalue`. - The address of an ` rvalue ref` parameter is an rvalue pointer (` rvalue(T)*`). - `is(T == rvalue)` is `true` for ` rvalue` types. - `cast( rvalue)` puts ` rvalue` on. - `typeid()` distinguishes ` rvalue` types. - implicit conversion for ` rvalue` is only allowed in one direction i.e from ` rvalue` to less. - The semantics of parameter overloading, function return values, `auto ref` and `auto rvalue ref` mentioned in the rvalue attribute section also apply here unchanged.
Oct 22
prev sibling parent Exil <Exil gmall.com> writes:
On Saturday, 28 September 2019 at 21:29:35 UTC, Manu wrote:
 On Sat, Sep 28, 2019 at 12:55 PM Exil via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 On Saturday, 28 September 2019 at 11:06:02 UTC, Suleyman wrote:
 [1] https://github.com/dlang/dmd/pull/10426
 [2] https://github.com/dlang/dlang.org/pull/2704
So was rvalue pre-approved or something? Last thing I heard about rvalue references is that they were rejected (along with the DIP) and a new DIP was being written. Was that forgone?
Completely different and unrelated topic. Passing rvalue temporaries by ref is different than rvalue references. It's not preapproved, this work is optimistic.
I wouldn't say they are completely different and unrelated. They both result in rvalues being attached to a reference. The only difference is one only allows rvalues specifically. It'd be a bad idea to allow both implementations, imo. It'd just complicate things further. Kind of a shame this was approved as a project, couldn't something else have been approved that didn't have a chance for the work to just be thrown away...
Oct 05
prev sibling parent Suleyman <sahmi.soulaimane gmail.com> writes:
Week 3 status:

   - ` rvalue` / `__rvalue` type constructor[1]:
     - implemented runtime type info[1][2]
     - `auto ref` infers ` rvalue`
       - `auto  rvalue ref` parameters expand to either `ref` or 
` rvalue ref`
       - `auto ref` parameters retain their current behavior
       - `auto ref` returns infer all three options `ref`, 
` rvalue ref`, and value.
     - implemented semantic for default arguments
     - implicit conversion is unidirectional, only from ` rvalue` 
to non ` rvalue` is allowed.
     - rvalue expressions are implicitly convertible to ` rvalue`
     - finding the common type of a binary expression is now aware 
of ` rvalue`
       - if both operands are ` rvalue` the result if ` rvalue`
       - else it's not ` rvalue`

____
[1] https://github.com/dlang/dmd/pull/10426
[2] https://github.com/dlang/druntime/pull/2814
Oct 05
prev sibling parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
Week 4:
     - ` rvalue` type:
         - fixed minor bugs
         - more documentation and a DIP will come later at 
milestone 4.
Oct 15
parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
Week 5:

Start of milestone 2.

* Move constructor semantic implemented based on the work on 
rvalue ref.
* A default move constructor is generated if one or more members 
of a struct have  move constructor.
* The move opAssign implemented as well.
* A ` move` attribute with an accompanying `__move()` intrinsic 
was added as an alternative to rvalue ref.

Usage example:

1. with rvalue ref

compile with the compiler switch `-preview=rvalueattribute`.
```
struct S
{
     static char[] result;
     this( rvalue ref inout S) inout { result ~= "Mc"; }
     void opAssign( rvalue ref inout S) inout { result ~= "Ma"; }
}

unittest
{
     S a;
     S b = cast( rvalue ref)a;
     a = cast( rvalue ref)b;
     assert(S.result == "McMa");
}
```

2. with the ` move` attribute

compile with the compiler switch `-preview=moveattribute`.
```
struct S
{
     static char[] result;
     this(ref inout S)  move inout { result ~= "Mc"; }
     void opAssign(ref inout S)  move inout { result ~= "Ma"; }
}

unittest
{
     S a;
     S b = __move(a);
     a = __move(b);
     assert(S.result == "McMa");
}
```

Note: the implementation is not ready yet for things like 
internal pointers, some interaction with the codegen is needed to 
eliminate the remaining blits that still exist.
Oct 23
next sibling parent reply RazvanN <razvan.nitu1305 gmail.com> writes:
On Wednesday, 23 October 2019 at 17:19:14 UTC, Suleyman wrote:
 Week 5:

 Start of milestone 2.

 [...]
The blits need to be eliminated only if the move constructor is defined, otherwise they should remain the same.
Oct 29
parent Suleyman <sahmi.soulaimane gmail.com> writes:
On Tuesday, 29 October 2019 at 15:20:14 UTC, RazvanN wrote:
 On Wednesday, 23 October 2019 at 17:19:14 UTC, Suleyman wrote:
 Week 5:

 Start of milestone 2.

 [...]
The blits need to be eliminated only if the move constructor is defined, otherwise they should remain the same.
Yes for the blits that have a reason to remain, like saving side effect. For redundant blits they will be simply eliminated.
Oct 29
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.com> writes:
On 10/23/19 1:19 PM, Suleyman wrote:
 Week 5:
 
 Start of milestone 2.
 
 * Move constructor semantic implemented based on the work on rvalue ref.
 * A default move constructor is generated if one or more members of a 
 struct have  move constructor.
 * The move opAssign implemented as well.
 * A ` move` attribute with an accompanying `__move()` intrinsic was 
 added as an alternative to rvalue ref.
 
 Usage example:
 
 1. with rvalue ref
 
 compile with the compiler switch `-preview=rvalueattribute`.
 ```
 struct S
 {
      static char[] result;
      this( rvalue ref inout S) inout { result ~= "Mc"; }
      void opAssign( rvalue ref inout S) inout { result ~= "Ma"; }
 }
 
 unittest
 {
      S a;
      S b = cast( rvalue ref)a;
      a = cast( rvalue ref)b;
      assert(S.result == "McMa");
 }
 ```
 
 2. with the ` move` attribute
 
 compile with the compiler switch `-preview=moveattribute`.
 ```
 struct S
 {
      static char[] result;
      this(ref inout S)  move inout { result ~= "Mc"; }
      void opAssign(ref inout S)  move inout { result ~= "Ma"; }
 }
 
 unittest
 {
      S a;
      S b = __move(a);
      a = __move(b);
      assert(S.result == "McMa");
 }
 ```
 
 Note: the implementation is not ready yet for things like internal 
 pointers, some interaction with the codegen is needed to eliminate the 
 remaining blits that still exist.
As far as I understand this is a major language change that proceeded without a known plan, and of which likelihood to be accepted is doubtful. This work must definitely be coordinated to the other related projects - binding rvalues to ref, move constructors, perfect forwarding, DIP 1014. We can't have different people work independently on their own vision of features that overlap 80%. Don't we risk adding this to our growing list of projects that people invest vast amounts of talent and work, just to abandon them?
Oct 29
parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
On Tuesday, 29 October 2019 at 15:31:55 UTC, Andrei Alexandrescu 
wrote:
 On 10/23/19 1:19 PM, Suleyman
 [...]
As far as I understand this is a major language change that proceeded without a known plan, and of which likelihood to be accepted is doubtful. This work must definitely be coordinated to the other related projects - binding rvalues to ref, move constructors, perfect forwarding, DIP 1014. We can't have different people work independently on their own vision of features that overlap 80%. Don't we risk adding this to our growing list of projects that people invest vast amounts of talent and work, just to abandon them?
DIP 1014 is postblit based I was advised by Manu to work on a constructor based solution for the same reasons that lead to the copy constructor being adopted in D. Prefect forwarding is a combination of auto ref and rvalue ref. Razvan told me he was working on perfect forwarding DIP and we talked superficially about it. The implementation of rvalue ref which is required for a perfect forwarding solution which doesn't do a copy or move at each level is available. There is also `auto rvalue ref` which exactly does perfect forwarding. Binding rvalues to ref is a separate issue. Even in C++ there is rvalue ref and const ref. The core of move semantics and perfect forwarding has been implemented. Whichever syntax is accepted in the end it will be just parser work. For example the implementation of the ` move` attribute - which is an alternative to rvalue ref just in case rvalue ref is not accepted - does actually use the rvalue ref implementation underneath, it's only parsed and mangled differently. If I knew of something else related to move semantics that was likelier to be accepted I would have included it in this SAOC. We surely need to collaborate. This work itself is a collaboration, I only did the implementation, the ideas are not mine. I give credits to all the contributors who shared their ideas on the initial discussion thread https://forum.dlang.org/thread/oipegxuwqmrmmzefrqcx forum.dlang.org. We can open a thread somewhere or anybody who is interested can just contact me directly in Slack.
Oct 29
next sibling parent Suleyman <sahmi.soulaimane gmail.com> writes:
On Tuesday, 29 October 2019 at 21:13:16 UTC, Suleyman wrote:
 [...] I give credits to all the contributors who shared their 
 ideas on the initial discussion thread [...]
I also give credits to my mentor Manu which explained and advised everything related related to this work.
Oct 29
prev sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 30/10/2019 10:13 AM, Suleyman wrote:
 
 We surely need to collaborate. This work itself is a collaboration, I 
 only did the implementation, the ideas are not mine. I give credits to 
 all the contributors who shared their ideas on the initial discussion 
 thread 
 https://forum.dlang.org/thread/oipegxuwqmrmmzefrqcx forum.dlang.org. We 
 can open a thread somewhere or anybody who is interested can just 
 contact me directly in Slack.
For projects like this if you want a workgroup channel on the Discord server please let us know. Having as many interested parties in live chat is a great way to develop and explore ideas.
Oct 29
parent Suleyman <sahmi.soulaimane gmail.com> writes:
On Wednesday, 30 October 2019 at 02:18:12 UTC, rikki cattermole 
wrote:
 On 30/10/2019 10:13 AM, Suleyman wrote:
 [...]
For projects like this if you want a workgroup channel on the Discord server please let us know. Having as many interested parties in live chat is a great way to develop and explore ideas.
This is a good idea.
Oct 30
prev sibling next sibling parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
Week 6:

A partial solution was implemented for issue 
https://issues.dlang.org/show_bug.cgi?id=20321.
A more complete solution is still work in progress.
Nov 01
parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
Week 7:

More progress on issue 20321. Made a second pull request[1].
Also audited all temporaries which are created in the glue layer 
of DMD and compiled a report about it[2]. This narrowed down the 
problem significantly. The report contains links to test cases 
and links to the pull request that has the fix if available.

[1] https://github.com/dlang/dmd/pull/10539
[2] 
https://gist.github.com/SSoulaimane/f87a9f86dc8808eab8ac787e237b47b2
Nov 11
parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
week 8:
   - finished the semantics of the default move opAssign
     - the default move opAssign is generated if:
       1. struct the move constructor
       2. one of struct fields defines the move opAssign
Nov 18
parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
Week 9:
   - fixed issue 20235[1] which was blocking std::string.
   - fixed issue 20413[2] which was blocking std::pair.


[1] https://issues.dlang.org/show_bug.cgi?id=20235
[2] https://issues.dlang.org/show_bug.cgi?id=20413
Nov 28
parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
Week 11:

GCC and Clang versions of std::vector were ported. Like the 
windows port version there is not range API yet, only arrays are 
accepted, for this reason the bitmap packed vector<bool> is not 
yet implemented. The Range interface is on the TODO list for the 
future.
Dec 11
next sibling parent Suleyman <sahmi.soulaimane gmail.com> writes:
On Wednesday, 11 December 2019 at 16:56:40 UTC, Suleyman wrote:
 Week 11:

 GCC and Clang versions of std::vector were ported. [...]
Pull request to `core.stdcpp.vector` https://github.com/dlang/druntime/pull/2866.
Dec 11
prev sibling parent reply bachmeier <no spam.net> writes:
On Wednesday, 11 December 2019 at 16:56:40 UTC, Suleyman wrote:
 Week 11:

 GCC and Clang versions of std::vector were ported. Like the 
 windows port version there is not range API yet, only arrays 
 are accepted, for this reason the bitmap packed vector<bool> is 
 not yet implemented. The Range interface is on the TODO list 
 for the future.
Could you expand a bit on this? Does it mean I can call a C++ function taking std::vector<double> as an argument with a double[] allocated on the D side?
Dec 11
parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
On Wednesday, 11 December 2019 at 17:02:47 UTC, bachmeier wrote:
 On Wednesday, 11 December 2019 at 16:56:40 UTC, Suleyman wrote:
 Week 11:

 GCC and Clang versions of std::vector were ported. Like the 
 windows port version there is not range API yet, only arrays 
 are accepted, for this reason the bitmap packed vector<bool> 
 is not yet implemented. The Range interface is on the TODO 
 list for the future.
Could you expand a bit on this? Does it mean I can call a C++ function taking std::vector<double> as an argument with a double[] allocated on the D side?
D doesn't have implicit constructors for function parameters otherwise you could do what you've described. But you can currently construct a vector and assign it from an array, it just won't do it automatically for function arguments for the reason mentioned. Example: ``` import core.stdcpp.vector; // construct vector!double v = [1.0, 2.1]; double[] a = []; // assign v = a; void f(vector!double); f(a); // error ```
Dec 11
parent reply bachmeier <no spam.net> writes:
On Wednesday, 11 December 2019 at 17:15:26 UTC, Suleyman wrote:
 On Wednesday, 11 December 2019 at 17:02:47 UTC, bachmeier wrote:
 On Wednesday, 11 December 2019 at 16:56:40 UTC, Suleyman wrote:
 Week 11:

 GCC and Clang versions of std::vector were ported. Like the 
 windows port version there is not range API yet, only arrays 
 are accepted, for this reason the bitmap packed vector<bool> 
 is not yet implemented. The Range interface is on the TODO 
 list for the future.
Could you expand a bit on this? Does it mean I can call a C++ function taking std::vector<double> as an argument with a double[] allocated on the D side?
D doesn't have implicit constructors for function parameters otherwise you could do what you've described. But you can currently construct a vector and assign it from an array, it just won't do it automatically for function arguments for the reason mentioned. Example: ``` import core.stdcpp.vector; // construct vector!double v = [1.0, 2.1]; double[] a = []; // assign v = a; void f(vector!double); f(a); // error ```
Okay. That's reasonable. Does v = a copy or can we reuse a.ptr with your implementation? Keep in mind that I don't know much about std::vector or the work you're doing.
Dec 11
parent Suleyman <sahmi.soulaimane gmail.com> writes:
On Wednesday, 11 December 2019 at 17:48:24 UTC, bachmeier wrote:
 [...]
Okay. That's reasonable. Does v = a copy or can we reuse a.ptr with your implementation? Keep in mind that I don't know much about std::vector or the work you're doing.
If you pass it a slice then it has to copy, and the reason being is that `vector!double` is short for `vector!(double, allocator!double)`, notice it has an allocator therefore it can't reuse the a pointer if the allocator is not the same. Even if hypothetically there was no allocator problem then a move operation - which is what you've described as reusing the slice pointer - can only be done if the constructor/opAssign of the vector knows that the slice is an rvalue (for example an array literal is an rvalue, or the result of an explicit move operation is also an rvalue) and I don't know of any way to declare a slice of rvalues right now. I will add a slice of rvalues as a type to my rvalue ref implementation (which will be documented and announced with a DIP in the next milestone). I was hesitant at first to allow slices of rvalues, but after porting std::vector I came across various move strategies among which was move iterators and since used slices instead, I found that I couldn't declare a move construtor/opAssign for slices, and I didn't, this is one of the lacking parts right now in the array API of vector, if you pass a slice it always has to copy no matter what.
Dec 11
prev sibling parent Suleyman <sahmi.soulaimane gmail.com> writes:
This marks the end of milestone 2 for which the objective was to 
implement user controlled move semantics in D.

Accomplished tasks:
- Implementation of the move constructor and move opAssign using 
rvalue ref or alternatively using the  move attribute.
- Fixing most cases of issue 20321 where the compiler copies 
objects without calling the copy or move constructor.

The following tasks will be continued after the SAOC period 
because they didn't fit the schedule of this milestone.
- Implement move semantics in druntime functions that perform 
array operations.
- Solve the two remaining cases of issue 20321.
Nov 18