ufcpp / UfcppSample

http://ufcpp.net/ 向けのサンプル
Apache License 2.0
136 stars 39 forks source link

stackalloc in nested contexts #260

Closed ufcpp closed 5 years ago

ufcpp commented 5 years ago

以下のようなコードを書けるようになるって話らしい。

using System;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        // この手の、式の中に stackalloc 埋め込みをさして「nested contexts」って言ってるみたい。
        // 16.2 Preview 1 でコンパイルできるようになってた。でも、IntelliSense 効いてない。
        if (stackalloc byte[1] == stackalloc byte[1]) ;
        M(stackalloc byte[1]);

        // こういう書き方は C# 7.3 時代からできてた。条件演算子だけ特別視?
        Span<byte> buf = len > 512 ? new byte[len] : stackalloc byte[len];

        // でもこれが今まではダメだった。
        // VS 16.2 Preview 1 ではコンパイルできる
        M(len > 512 ? new byte[len] : stackalloc byte[len]);
    }

    static void M(Span<byte> buf) => buf[0] = 1;

    static async Task MAsync()
    {
        M(stackalloc byte[1]); // これは OK になったっぽい。
        await Task.Yield();

        {
            Span<byte> buf = stackalloc byte[1]; // これは相変わらずダメ。{} でくくっててもダメ。
        }
    }
}

16.2 Preview 1 で有効化されてること確認。 相変わらず、非同期メソッド内だと {} で囲んでようとダメ。

ufcpp commented 5 years ago

Issue #1412, trivial to implement in 8.0, where the stack-spilling machinery is there anyway for pattern matching.」らしい。 パターンマッチングのついでだからほとんどコストがかからないとのこと。

ufcpp commented 5 years ago

実行してみたら InvalidProgramException 発生。 ランタイム側の修正必要で、 .NET Core 3.0 Preview 6 待ちとかかな?

using System;

class Program
{

    static void Main()
    {
        M(stackalloc byte[1]);
    }

    static void M(Span<byte> buf) => buf[0] = 1;
}

↑ 既知バグ(Preview 2 まで治らない)、かつ、 stackalloc を Span に代入するだけで起こるっぽい。

ufcpp commented 5 years ago

フィールド初期化子とかに対しても使えるらしい。

using System;

class Program
{
    static int Init(Span<byte> buffer) => 0;

    int a = Init(stackalloc byte[8]);

    static void Main()
    {
    }
}
ufcpp commented 5 years ago

https://ufcpp.net/study/csharp/cheatsheet/ap_ver8/#nested-stackalloc