kubo39's blog

ただの雑記です。

小ネタ: safe functionとcast function of null

おなじみ(?), safe functionを考えてみようの会です.

突然ですが, 以下のコードは合法でしょうか?

void main() @safe
{
    (cast(void function() @safe) null)();
}

結果はおおかた予想がつくとは思いますが、Segmentation Faultになります。

(dmd-2.084.0)$ rdmd safecastnull.d
zsh: segmentation fault (core dumped)  rdmd safecastnull.d

さて、合法かどうかですが, まず safe functionの定義 から照らし合わせてみると

  • No casting from a pointer type to any type other than void*.
  • No casting from any non-pointer type to a pointer type.
  • No pointer arithmetic (including pointer indexing).
  • Cannot access unions that have pointers or references overlapping with other types.
  • Calling any system functions.
  • No catching of exceptions that are not derived from class Exception.
  • No inline assembler.
  • No explicit casting of mutable objects to immutable.
  • No explicit casting of immutable objects to mutable.
  • No explicit casting of thread local objects to shared.
  • No explicit casting of shared objects to thread local.
  • No taking the address of a local variable or function parameter.
  • Cannot access __gshared variables.
  • Cannot use void initializers for pointers.
  • Cannot use void initializers for class or interface references.

一個目と二個目が怪しいですね.

nullの定義 もみてみましょう. 最初の文はnullはポインタやら動的配列やらを表すことができる値と解釈できます.

次ですが, なんと, "it is an exact conversion to convert it to the null value for pointers, pointers to functions, delegates, etc." という文言が確認できます. 正しい変換であるとはどういうことなんなんでしょうか. 必ずsafe? また直前のnullは別の型にキャストされる前だとtypeof(null)という型が与えられるそうですが, これはpointer typeなのでしょうか, それともnon-pointer typeなのでしょうか. 少なくとも現在の仕様の状態から判別することは難しいと思います…

というわけで最初の問題の結論は, 「現時点(2019.02.07)での仕様ではどちらともとれる」でした(これはひどい)