Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP8の新機能をPHP内部コードのテストphptから読む / Learn PHP8 by reading phpt

PHP8の新機能をPHP内部コードのテストphptから読む / Learn PHP8 by reading phpt

PHP Conference Japan 2020での登壇資料です。

PHP 8 の新機能のふるまいを、php内部のテストコードを通じて、理解する時間を提供します。PHP 8 がもうじきリリースされる昨今で、 PHP 8 についての新機能についての関心も高まってきました。さまざまな新機能の抑え方がありますが、ひとつが、テストコードを通じて対象システムを理解する方法です。

phptというものがあります。これは、 PHP 内部コード、つまり php-src の自動テストスクリプトです。ここには、PHP という言語自体の committer たちがどういう振る舞いを PHP に与えたのか、それがレアケースのユースケースも含めて記述されています。

テストコードを書く皆様であれば、 Test as Document 、仕様を伝えるドキュメントとしてのテスト、を自身が運用するアプリケーションに対して書きますよね。phpt は PHP 8 の新機能に対するテストコードも含んでいます。コードの読み手が、テストコードを通じて、 PHP 自体の振る舞いを理解する。phpt に記述されたコードを通して、phpt の読み方を知り PHP 8 の新機能を押さえましょう。

具体的には、PHP 8 の新機能である Named Arguments・Match expression v2・Nullsafe operator・Union Types v2・Mixed type v2を題材にします。

Kazuki Higashiguchi
PRO

December 12, 2020
Tweet

More Decks by Kazuki Higashiguchi

Other Decks in Technology

Transcript

  1. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    2020.12.12 PHP Conference Japan 2020
    @hgsgtk Kazuki Higashiguchi
    PHP8の新機能を
    PHP内部コードのテスト
    phptから読む
    1

    View Slide

  2. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    当発表で得られるもの



    PHP8の新機能を理解できる
    PHP内部コードのテスト phpt の読
    み方がわかる
    PHPの機能をドキュメントだけでなく、
    テストコードから調べられるようになる
    2

    View Slide

  3. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon 3
    phptからPHP8の新機能を読む
    ※ PHP内部構造の図は『Quick tour of PHP
    from inside』を参考
    https://www.slideshare.net/jpauli/quick-t
    our-of-php-from-inside

    View Slide

  4. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    @hgsgtk Kazuki Higashiguchi
    東京に住まう Software Developer
    BASE BANK, Inc. Full Cycle Developer / Tech Lead
    自己紹介
    4
    Dockerアプリケーション開
    発実践ガイド
    > コンテナアプリケーションの設計
    セオリー
    https://gihyo.jp/magazine/SD/archive/2020/202012
    PHPにおけるユニットテス
    トとCI/CD
    > ユニットテストの育て方
    https://gihyo.jp/book/2019/978-4-297-11055-0

    View Slide

  5. #phpcon © 2012-2020 BASE, Inc. 5
    “PHP Interpreter”の
    テスティングフレームワーク

    View Slide

  6. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    “PHP Interpreter”のテスティングフレームワーク
    PHP自体のコード”The PHP Interpreter”(https://github.com/php/php-src)
    php-srcには、テストスイートとその結果を記録・レポートするテスティングフレームワー
    クが用意されている(https://qa.php.net/running-tests.php)
    PHPをビルドする過程で生成したMakefileを用いてmake testで実行する
    テスティングフレームワークとしての機能(run-tests.php)
    - テストスイート(*.phpt)の収集
    - SUT (System Under Test) の実行
    - 期待値を検証する
    - テスト結果のレポーティング
    6

    View Slide

  7. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    実行時の構造
    7
    $ make test
    TEST_PHP_EXECUTABLE=sapi/cli/php sapi/cli/php run-tests.php
    See also 『ソースコード(php-src)からPHPをビルドする流れと仕組みを手を動かしながら理解する』

    View Slide

  8. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    make test実行結果
    8
    $ make test
    ...(省略)
    ===========
    TIME START 2020-12-11 08:32:20
    ===========
    PASS EXPECT [tests/run-test/test001.phpt]
    PASS EXPECTF [tests/run-test/test002.phpt]
    PASS EXPECTREGEX
    [tests/run-test/test003.phpt]
    PASS INI section allows '='
    [tests/run-test/test004.phpt]
    … (省略)
    ... (省略)
    ===================
    TEST RESULT SUMMARY
    -------------
    Exts skipped : 45
    Exts tested : 27
    -------------
    Number of tests : 16033 11240
    Tests skipped : 4793 ( 29.9%) --------
    Tests warned : 0 ( 0.0%) ( 0.0%)
    Tests failed : 4 ( 0.0%) ( 0.0%)
    Expected fail : 31 ( 0.2%) ( 0.3%)
    Tests passed : 11205 ( 69.9%) ( 99.7%)
    ===================

    View Slide

  9. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    テストスクリプト phpt
    9
    PHP内部およびQAチームがPHPの機能をテストするために使用されるスクリプト
    新機能追加時に書かれ、既存のバグを検知する回帰テストの役割も兼ねる
    $ find . -name 'tests' -type d
    ./php-src/tests PHP内部のテスト
    ./php-src/Zend/tests Zend(PHPコア部分)のテスト
    ./php-src/ext/*/tests PHP Extensionのテスト
    ./php-src/sapi/*/tests SAPIのテスト
    $ find . -name '*.phpt' | wc -l
    16033
    ※ 2020年12月11日段階の筆者環境でのphptファイル件数

    View Slide

  10. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    PHPの関数とphptテストの一覧
    10
    「この関数のテストファイルどこかな?」を探すときにちょっと便利
    http://gcov.php.net/viewer.php?version=PHP_HEAD&func=tested_functions

    View Slide

  11. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    phptファイルの読み方
    --TEST--
    テストタイトル
    --FILE--
    テストの入力となるPHPスクリプト

    --EXPECT--
    テスト結果の期待値
    (ex. var_dump, echo)
    ※ その他のファイルセクション仕様
    https://qa.php.net/phpt_details.php
    11
    https://github.com/php/php-src/blob/0e60b812c05ed5e3704ab6f31f29040040c3edd7/ext/standard/tests/
    strings/strtr.phpt#L2
    php-src/ext/standard/tests/strings/strtr.phpt

    View Slide

  12. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    phptファイルの「命名規則」
    phptファイルは命名規則が設定されている。
    現実としてはすべてがこの規則に沿っているわけではないが、
    どういった種類のテストがあるか傾向を知れる。
    ● bug.phpt : Tests for bugs
    ● _basic.phpt : Tests for a function's basic behaviour
    ● _error.phpt : Tests for a function's error behaviour
    ● _variation.phpt : Tests for variations in a function's behaviour
    ● .phpt : General tests for extensions
    https://qa.php.net/write-test.php#naming-conventions
    12

    View Slide

  13. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    bug.phpt
    bugs.php.net に起票されたbugidに対応するテストケース
    $ find . -name 'bug*.phpt' | wc -l
    3957
    13
    https://github.com/php/php-src/blob/7aacc705d038
    87c64a90489e367f4c40b46aa3c2/tests/basic/bug54
    514.phpt#L2
    ex. bug54515.phpt
    https://bugs.php.net/bug.
    php?id=54514

    View Slide

  14. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    _basic.phpt
    関数に対するシンプルなパターンのテストケースが記述さ
    れる
    $ find . -name '*_basic.phpt' | wc -l
    892
    ex.
    ext/standard/tests/assert/assert_basic.phpt
    → assert実行時にcallbackが走るか
    14
    https://github.com/php/php-src/blob/7aacc705d03887c64a90489e367f
    4c40b46aa3c2/ext/standard/tests/assert/assert_basic.phpt#L2

    View Slide

  15. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    _error.phpt
    関数に対するエラーのテストケースが記述される
    $ find . -name '*_error.phpt' | wc -l
    350
    ex.
    Zend/tests/generators/errors/count_error.phpt
    → Generatorを count() に渡した際にエラーになるか
    15
    https://github.com/php/php-src/blob/2ee7e2982f5609ca6c3837c0b93ba9c5e89f84cb/Zend/tests/generators/e
    rrors/count_error.phpt#L2

    View Slide

  16. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    _variation.phpt
    16
    境界条件をテストするといったバリエーションを扱いたい
    場合のテスト
    $ find . -name '*_variation.phpt' | wc -l
    74
    ex.
    ext/standard/tests/math/sin_variation.phpt
    → 正弦を求めるsin関数のバリエーションテスト
    https://github.com/php/php-src/blob/0c6d06ecfa8f75f5afc4daf852a76c90
    5b672b25/ext/standard/tests/math/sin_variation.phpt#L2

    View Slide

  17. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    .phpt
    17
    PHP Extensionの一般的なテストをする際のテ
    ストです。
    ex.
    ext/dba/tests/dba003.phpt
    → Database Extensionのテスト
    https://github.com/php/php-src/blob/c5401854fcea27ff9aabfd0682ff4d81
    bbb3c888/ext/dba/tests/dba003.phpt#L2

    View Slide

  18. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    実際のphptファイル
    前述したとおりすべてがそのphptファイルの規則というわけではない。
    しかし、ファイル名から命名規則のどれに該当するかでおおまかに内容が類推できる。
    ex. Named Arguments機能のphptテストファイル
    $ tree -L 1 Zend/tests/named_params/
    Zend/tests/named_params/
    ├── __call.phpt // Named Argumentsが __call で機能してるか
    ├── assert.phpt // assertをNamed Argumentsとともに
    ├── basic.phpt // _basicの命名規則に該当する内容
    ├── cannot_pass_by_ref.phpt // エラーケース(参照渡し)
    ├── duplicate_param.phpt // エラーケース(同一引数に重複して渡した)
    └── // (省略)
    18

    View Slide

  19. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    特定のテストを実行したい場合(make test)
    TESTSオプションに実行したいテストファイル名を指定する
    ディレクトリ以下全ケースの場合は/* (ex. Zend/tests/named_params/*)
    $ make test TESTS='--show-diff
    Zend/tests/named_params/duplicate_param.phpt'
    Running selected tests.
    PASS Duplicate param [Zend/tests/named_params/duplicate_param.phpt]
    =============
    Number of tests : 1 1
    ...(省略)
    Tests passed : 1 (100.0%) (100.0%)
    19
    See also 『PHP extensionのmake testに関するTIPS - @hnw』
    (https://qiita.com/hnw/items/f70e52eaa065ae573668#teststests002phpt)

    View Slide

  20. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    失敗時の差分をみる(--show-diff)
    TESTSオプションに--show-diffを指定することで失敗時の差分が表示される
    $ make test TESTS='--show-diff
    Zend/tests/named_params/duplicate_param.phpt'
    Running selected tests.
    TEST 1/1 [Zend/tests/named_params/duplicate_param.phpt]
    ========DIFF========
    001+ 2 Named parameter $a overwrites previous argument
    001- Named parameter $a overwrites previous argument
    ========DONE========
    FAIL Duplicate param [Zend/tests/named_params/duplicate_param.phpt]
    20
    See also 『PHP extensionのmake testに関するTIPS - @hnw』
    (https://qiita.com/hnw/items/f70e52eaa065ae573668#teststests002phpt)

    View Slide

  21. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    phpt を読むことで得られるもの
    PHP Userは、php.netを閲覧することで言語機能
    の使い方を知れるが、主に正常系と限定的であ
    る。
    PHP自体・コアに対するテストコードである phpt
    を読むことで、正常ケース以外も境界値やエラー
    ケースの仕様を把握できる。
    Cに不慣れであっても読みやすく、php-srcのコー
    ドを読み始める第一歩となる。
    21

    View Slide

  22. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    読んでいくPHP8 New Features
    22



    Named Arguments
    4
    5
    6
    Constructor property promotion
    Attributes
    Union Types
    Match expression
    Nullsafe operator

    View Slide

  23. #phpcon © 2012-2020 BASE, Inc. 23
    - PHP8 New Feature -
    Named Arguments

    View Slide

  24. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Named Arguments
    引数に名前をつけて渡すことが出来る
    RFC: https://wiki.php.net/rfc/named_params
    PR: https://github.com/php/php-src/pull/5357
    (主な)phpt files: Zend/test/named_params/* (30 files)
    24

    View Slide

  25. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Named Arguments
    [Merits]
    1. 引数が多い場合に順番を気にしなくてもよくなる
    2. htmlspecialchars()のようにデフォルト値が多い引数の場合に記述が簡潔になる
    3. 意味がわかりにくい引数を渡す場合のコードの自己記述性の向上
    25

    View Slide

  26. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    $ tree -L 1 Zend/test/named_params
    ├── __call.phpt
    ├── basic.phpt
    ├── duplicate_param.phpt
    ├── missing_param.phpt
    ├── runtime_cache_init.phpt
    ├── undef_var.phpt
    ├── unknown_named_param.phpt
    ├── unpack.phpt
    ├── unpack_and_named_1.phpt
    ├──
    ├── (省略)
    └── variadic.phpt
    26
    主なphptテストファイル一覧

    View Slide

  27. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    基本的なテストケース
    27
    Zend/tests/named_params/basic.phpt
    [テストケースから読み取れる仕様]
    ● “positional argument”と”Named Argument”の併用が
    可能
    https://github.com/php/php-src/blob/d92229d8c78aac25925284e23aa790
    3dca9ed005/Zend/tests/named_params/basic.phpt#L2

    View Slide

  28. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    未定義変数を引数に渡した場合
    28
    Zend/tests/named_params/undef_var.phpt
    [テストケースから読み取れる仕様]
    ● 未定義変数を渡した場合Warningとなり当該
    箇所はNULLが値として設定される
    https://github.com/php/php-src/blob/6992c38ecc512a00b80af64d5422470
    dd1e74c36/Zend/tests/named_params/undef_var.phpt#L2

    View Slide

  29. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    重複して2回渡した場合
    29
    Zend/tests/named_params/undef_var.phpt
    [テストケースから読み取れる仕様]
    ● 重複して2回同じ引数に値を渡した場合例外Error
    が発生
    ○ Named parameter $%s overwrites previous
    argument
    test(a: 1 a: 2);
    https://github.com/php/php-src/blob/d92229d8c78aac25925284e23a
    a7903dca9ed005/Zend/tests/named_params/duplicate_param.phpt#L2

    View Slide

  30. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon 30
    Deep Dive into PHP Internal
    [テストケースから内部実装を覗く]
    ● 重複して2回同じ引数に値を渡した
    場合例外Errorが発生
    ○ Named parameter $%s
    overwrites previous argument
    これはどのような実装によって実現さ
    れているのか?

    View Slide

  31. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    重複して2回渡した場合のエラー発生コード
    “Named parameter $%s overwrites previous argument”でgrepして見つける
    31
    zend_execute.c
    https://github.com/php/php-src/blob/77325c4448cff9d031b86c39493
    2acb072e99bfe/Zend/zend_execute.c#L4431

    View Slide

  32. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    そもそもZend Engineとは
    [Zend VM]
    PHPの中間コードを実行する仮想CPU実装
    オペコード列を実行する機能
    See also:
    @hnwさん『Zend VMにおける例外の実装』
    (https://www.slideshare.net/hnw/zend-vm-227589843)
    32

    View Slide

  33. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    PHPコード実行サイクル内のzend_execute
    33
    zend_execute.c
    See also:
    julien pauliさん『Quick tour of PHP from inside』
    (https://www.slideshare.net/jpauli/quick-tour-of-php-from-inside)
    ● Startup: メモリアロケーション
    ● zend_compile_file(): コンパイル
    ○ (字句解析・構文解析・OPCode生成)
    ● zend_execute(): OPCode実行
    ● Shutdown: メモリ解放
    →今回のエラーハンドリングはzend_executeフェーズ

    View Slide

  34. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon 34
    Cコードをいじってみてテストで確かめる
    ちょっとCコードを微修正してテストを走らせるとCコードレベルで理解する取っ掛か
    りになる
    $ make test TESTS='--show-diff
    Zend/tests/named_params/duplicate_param.phpt'
    ========DIFF========
    001+ 2 Named parameter $a overwrites previous argument
    001- Named parameter $a overwrites previous argument
    ========DONE========
    FAIL Duplicate param [Zend/tests/named_params/duplicate_param.phpt]

    View Slide

  35. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    phpスクリプトとCコードの対応
    35
    Zend/tests/named_params/duplicate_param.phpt Zend/zend_execute.c
    Cコードのエラーメッセージを
    区別がつくように修正して
    テストを再実行した

    View Slide

  36. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    エラーケースの仕様をphptから理解する
    Named Argumentsについてドキュメントでは詳
    細記載されていないエラー系の仕様をテストコー
    ドを通じて知った。
    「こういう時エラーになるのかな?」
    「言語機能として期待した振る舞いなのか?」
    PHP内部実装について紐解いていくきっかけとな
    る。内部のCコードとの対応付けを部分的に理解し
    ていくことを積み重ねる
    36

    View Slide

  37. #phpcon © 2012-2020 BASE, Inc. 37
    - PHP8 New Feature -
    Constructor property
    promotion

    View Slide

  38. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Constructor property promotion
    Constructorの引数にアクセス修飾子を足す
    ことでプロパティ宣言と対応させる
    RFC:
    https://wiki.php.net/rfc/constructor_p
    romotion
    PR:
    https://github.com/php/php-src/pull/5
    291
    (主な)phpt files:
    Zend/tests/ctor_*.phpt
    (16 files)
    38

    View Slide

  39. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Constructor property promotion
    すべてのプロパティ属性に使用しなくてもいい。Constructorで渡す必要のない内部管理の
    状態などと使い分け。
    39

    View Slide

  40. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    主なphptテストファイル一覧
    $ ls Zend/tests/ctor*
    ctor_promotion_abstract.phpt
    ctor_promotion_additional_modifiers.phpt
    ctor_promotion_attributes.phpt
    ctor_promotion_basic.phpt
    ctor_promotion_by_ref.phpt
    ctor_promotion_callable_type.phpt
    ctor_promotion_defaults.phpt
    ctor_promotion_free_function.phpt
    ctor_promotion_interface.phpt
    ctor_promotion_mixing.phpt
    ctor_promotion_not_a_ctor.phpt
    40
    ctor_promotion_null_default.phpt
    ctor_promotion_repeated_prop.phpt
    ctor_promotion_trait.phpt
    ctor_promotion_untyped_default.phpt
    ctor_promotion_variadic.phpt

    View Slide

  41. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    基本的なテストケース
    41
    Zend/tests/ctor_promotion_basic.phpt
    [テストケースから読み取れる仕様]
    ● Constructor property promotionの基本的な使い方
    https://github.com/php/php-src/blob/064b4644484d38e9dce40ae
    f7e8e0e8190e9d863/Zend/tests/ctor_promotion_basic.phpt#L2

    View Slide

  42. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    abstractクラスでの利用
    42
    [テストケースから読み取れる仕様]
    ● abstractクラスで使用した場合はFatal
    Error
    ※ RFC内で制約として記載されてはいる
    https://github.com/php/php-src/blob/064b4644484d38e9dce40aef7e8e0e8190e9d863/Zend/tests/ctor_promotio
    n_abstract.phpt#L2
    Zend/tests/ctor_promotion_abstract.phpt

    View Slide

  43. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Callable typeとの併用
    43
    [テストケースから読み取れる仕様]
    ● callableタイプはサポートしていない
    RFC内で制約として記載されてはいるが、
    クラスのproperty typeとしてcallableがサ
    ポートされていないため
    https://github.com/php/php-src/blob/064b4644484d38e9dce40aef7e8e0e8190e9d863/Zend/tests/ctor_promotio
    n_callable_type.phpt#L2
    Zend/tests/ctor_promotion_callable_type.phpt

    View Slide

  44. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Trait内で使う
    44
    [テストケースから読み取れる仕様]
    ● trait内で使用可能
    RFCにもしれっと一行書いてるくらいの内容
    While unusual, promoted parameters
    may occur inside trait constructors.
    https://github.com/php/php-src/blob/064b4644484d38e9dce40aef7e8e0e8190e9d863/Zend/tests/ctor_promotio
    n_trait.phpt#L2
    Zend/tests/ctor_promotion_trait.phpt

    View Slide

  45. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    nullable typeでない型にnullを指定した
    45
    [テストケースから読み取れる仕様]
    ● nullable typeではないプロパティのデ
    フォルト値にnull指定不可
    https://github.com/php/php-src/blob/064b4644484d38e9dce40aef7e8e0e8190e9d863/Zend/tests/ctor_promotio
    n_null_default.phpt#L2
    Zend/tests/ctor_promotion_null_default.phpt

    View Slide

  46. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    ...$var(variadic param)の使用
    46
    [テストケースから読み取れる仕様]
    ● variadic param(...$var)は使用不可
    https://github.com/php/php-src/blob/064b4644484d38e9dce40aef7e8e0e8190e9d863/Zend/tests/ctor_promotio
    n_variadic.phpt#L2
    Zend/tests/ctor_promotion_variadic.phpt

    View Slide

  47. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    微妙なユースケースについてphptで理解する
    Constructor property promotionについてRFC
    をじっくり読まないと気が付きにくい微妙なユー
    スケース仕様をphptを通じて知った。
    「abstract classはいけるんだっけ?」
    「callable typeだと使えないかな?」
    「classはいけるけどtraitはどうだっけ?」
    47

    View Slide

  48. #phpcon © 2012-2020 BASE, Inc. 48
    - PHP8 New Feature -
    Attributes

    View Slide

  49. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Attributes
    49
    クラス・プロパティ...etcも構造化・構文的な
    メタデータとしての属性定義
    Annotations in Java
    Attributes in C#, C++, Rust, Hack
    Decorators in Python, Javascript
    RFC: https://wiki.php.net/rfc/attributes_v2
    PR: https://github.com/php/php-src/pull/5394
    (主な)phpt files:
    Zend/tests/attributes/* (33 files)

    View Slide

  50. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    主なphptテストファイル一覧
    $ ls Zend/tests/attributes/
    001_placement.phpt
    002_rfcexample.phpt
    003_ast_nodes.phpt
    004_name_resolution.phpt
    005_objects.phpt
    006_filter.phpt
    007_self_reflect_attribute.phpt
    008_wrong_attribution.phpt
    009_doctrine_annotations_example.phpt
    010_unsupported_const_expression.phpt
    011_inheritance.phpt
    (省略)
    50
    029_reflect_internal_symbols.phpt
    030_strict_types.inc
    030_strict_types.phpt
    031_backtrace.phpt
    032_attribute_validation_scope.phpt

    View Slide

  51. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Named Argumentsとの組み合わせ
    51
    Zend/tests/named_params/attribute
    s.phpt
    [テストケースから読み取れる仕様]
    ● “Attribute”に対しても”Named
    Argument”が使用可能
    #[MyAttribute('A', c: 'C')]
    class Test1 {}
    https://github.com/php/php-src/blob/8b37c1e993f17345312a76a239b77ae137d3f8e8/Zend/tests/named_params
    /attributes.phpt#L2

    View Slide

  52. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Constructor property promotionと組み合わせ
    52
    [テストケースから読み取れる仕様]
    ● Constructor property promotionで作ら
    れるプロパティにもAttribute設定可能
    public function __construct(
    #[NonNegative]
    public int $num,
    ) {}
    https://github.com/php/php-src/blob/8b37c1e993f17345312a76a239b77ae137d3f8e8/Zend/tests/ctor_promotio
    n_attributes.phpt#L2
    Zend/tests/ctor_promotion_attributes.phpt

    View Slide

  53. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    AttributeのGroup化
    53
    [テストケースから読み取れる仕様]
    ● class/functionに対して複数のAttribute
    を設定
    https://github.com/php/php-src/blob/8b37c1e993f17345312a76a239b77ae137d3f8e8/Zend/tests/attributes/02
    8_grouped.phpt#L2
    Zend/tests/attributes/028_grouped.phpt

    View Slide

  54. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Doctrine-likeなAttribute使用
    54
    [テストケースから読み取れる仕様]
    ● Attribute実装時にコミッターがDoctrine
    のようなユースケースを想定したこと
    当機能コミッターの@beberleiがDoctrineコ
    アコミッターである背景が垣間見える
    (個人の感想です)
    https://github.com/php/php-src/blob/8b37c1e993f17345312a76a239b77ae137d3f8e8/Zend/tests/attributes/00
    9_doctrine_annotations_example.phpt#L2
    Zend/tests/attributes/009_doctrine_ann
    otations_example.phpt

    View Slide

  55. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    機能の組み合わせ可能性をphptで理解する
    各機能単体では気が付かないかもしれない新機能
    の組み合わせの仕様をphptを通じて知った。
    「Attributes && Named Argument」
    「Attributes && Constructor property
    promotion」
    テストケースからコミッターの実装時の考慮事項
    ・背景が少し浮かび上がって見えた。
    55

    View Slide

  56. #phpcon © 2012-2020 BASE, Inc. 56
    - PHP8 New Feature -
    Union Types

    View Slide

  57. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Union Types
    複数の異なる型の値を受け付ける型宣言
    RFC:
    https://wiki.php.net/rfc/union_types_
    v2
    PR:
    https://github.com/php/php-src/pull/4
    838
    (主な)phpt files:
    Zend/tests/type_declarations/union_ty
    pes/* (30 files)
    57

    View Slide

  58. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    $ tree -L 2 Zend/tests/type_declarations/union_types/
    ├── generator_return_containing_extra_types.phpt
    ├── (省略)
    ├── redundant_types
    │ ├── (省略)
    │ └── object_and_static.phpt
    ├── standalone_false.phpt
    ├── (省略)
    ├── variance
    │ ├── (省略)
    │ └── valid.phpt
    └── void_with_class.phpt
    58
    主なphptテストファイル一覧

    View Slide

  59. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    null単体で使用した場合
    59
    Zend/tests/type_declarations/union_
    types/standalone_null.phpt
    [テストケースから読み取れる仕様]
    ● Nullable union typesは仕様としてある
    が、null単体の使用は不可
    php.netにも注意書きがある仕様
    https://www.php.net/manual/en/language.types.declarations.php#la
    nguage.types.declarations.union
    https://github.com/php/php-src/blob/999e32b65a8a4bb59e27e538fa68ffae4b99d863/Zend/tests/type_declarati
    ons/union_types/standalone_null.phpt#L2

    View Slide

  60. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    false単体で使用した場合
    60
    Zend/tests/type_declarations/union_
    types/standalone_false.phpt
    [テストケースから読み取れる仕様]
    ● false pseudo-typesは仕様としてある
    が、false単体の使用は不可
    all of false, false|null and ?false are
    not permitted (php.net)
    https://github.com/php/php-src/blob/999e32b65a8a4bb59e27e538fa68ffae4b99d863/Zend/tests/type_declarati
    ons/union_types/standalone_false.phpt#L2

    View Slide

  61. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    voidをUnionTypeで使用した場合
    61
    Zend/tests/type_declarations/union_
    types/void_with_class.phpt
    [テストケースから読み取れる仕様]
    ● voidはUnionTypeでは使用不可
    RFCでは言及されている内容
    The void type can never be part of a
    union. As such, types like T|void are
    illegal in all positions, including
    return types.
    https://github.com/php/php-src/blob/999e32b65a8a4bb59e27e538fa68ffae4b99d863/Zend/tests/type_declarati
    ons/union_types/void_with_class.phpt#L2

    View Slide

  62. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    strictモード有効・無効時の挙動
    62
    https://github.com/php/php-src/blob/999e32b65a8a4bb59e27e538fa68ffae4b99d863/Zend/tests/type_declarati
    ons/union_types/type_checking_strict.phpt#L2
    https://github.com/php/php-src/blob/999e32b65a8a4bb59e27e538fa68ffae4b99d863/Zend/tests/type_declarati
    ons/union_types/type_checking_weak.phpt#L2
    [type_checking_weak.phpt - 無効]
    Type int|string|null:
    42 => 42
    42.0 => 42
    INF => "INF"
    "42" => "42"
    (省略)
    true => 1
    false => 0
    null => null
    [] => Type Error
    new stdClass => Type Error
    new WithToString => "__toString()"
    [type_checking_strict.phpt - 有効]
    Type int|string|null:
    42 => 42
    42.0 => Type Error
    INF => Type Error
    "42" => "42"
    (省略)
    true => Type Error
    false => Type Error
    null => null
    [] => Type Error
    new stdClass => Type Error
    new WithToString => Type Error

    View Slide

  63. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    バリエーションに伴う仕様をphptで理解する
    Union Typesを用いるバリエーションとそれに伴
    う仕様についてphptから知った。
    「Union Typesで使用不可な『型』はなにか」
    「strictモード有効にした場合int|string|nullの
    引数に対してどのような挙動となるか」
    63

    View Slide

  64. #phpcon © 2012-2020 BASE, Inc. 64
    - PHP8 New Feature -
    Match expression

    View Slide

  65. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Match expression
    match式の導入、switch文に類似するが値を
    返すため、直接 return したりできる
    RFC:
    https://wiki.php.net/rfc/match_expres
    sion_v2
    PR:
    https://github.com/php/php-src/pull/5
    371
    phpt files:
    Zend/tests/match/* (24 files)
    65

    View Slide

  66. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    $ ls Zend/tests/match/
    001.phpt
    002.phpt
    003.phpt
    004.phpt
    005.phpt
    006.phpt
    007.phpt
    008.phpt
    009.phpt
    011.phpt
    012.phpt
    017.phpt
    66
    主なphptテストファイル一覧
    023.phpt
    024.phpt
    027.phpt
    028.phpt
    029.phpt
    030.phpt
    037.phpt
    038.phpt
    039.phpt
    040.phpt
    041.phpt
    042.phpt

    View Slide

  67. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    基本的なユースケース
    67
    Zend/tests/match/001.phpt
    [テストケースから読み取れる仕様]
    ● match式をreturnに利用する基本的な利用シーン
    https://github.com/php/php-src/blob/9fa1d1330138ac424f990ff03e62721
    120aaaec3/Zend/tests/match/001.phpt#L2

    View Slide

  68. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    条件判定を組み合わせる場合
    68
    Zend/tests/match/004.phpt
    [テストケースから読み取れる仕様]
    ● match式内で条件を書く場合の想定コード
    https://github.com/php/php-src/blob/9fa1d1330138ac424f990ff03e62721
    120aaaec3/Zend/tests/match/004.phpt#L2

    View Slide

  69. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    match式内に該当するケースが無い場合
    69
    Zend/tests/match/007.phpt
    [テストケースから読み取れる仕様]
    ● match式内でケースに該当するものがない場合
    Fatal errorが発生する
    https://github.com/php/php-src/blob/9fa1d1330138ac424f990ff03e62721
    120aaaec3/Zend/tests/match/007.phpt#L2

    View Slide

  70. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    1ケースに複数条件を指定する
    70
    Zend/tests/match/008.phpt
    [テストケースから読み取れる仕様]
    ● match式内で複数条件を指定可能
    https://github.com/php/php-src/blob/9fa1d1330138ac424f990ff03e62721
    120aaaec3/Zend/tests/match/008.phpt#L2

    View Slide

  71. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    条件リストの最後もコンマ(,)
    71
    Zend/tests/match/041.phpt
    [テストケースから読み取れる仕様]
    ● 条件リストの最後もコンマ(,)を指定している
    場合
    https://github.com/php/php-src/blob/9fa1d1330138ac424f990ff03e62721
    120aaaec3/Zend/tests/match/041.phpt#L2

    View Slide

  72. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    細かい挙動をphptで理解する
    Match Expressionを用いる際の細かい仕様につい
    てphptから知った。
    「matchの条件リストの最後コンマ(,)入れれる
    の?」
    「条件リストに合致しなかった場合はどういう振
    る舞いになる?」
    72

    View Slide

  73. #phpcon © 2012-2020 BASE, Inc. 73
    - PHP8 New Feature -
    Nullsafe operator

    View Slide

  74. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Nullsafe operator
    nullチェックを入念にしていたものは、
    nullsafe演算子によってチェーン実行できる
    RFC:
    https://wiki.php.net/rfc/nullsafe_oper
    ator
    PR:
    https://github.com/php/php-src/pull/5
    619
    phpt files:
    Zend/tests/nullsafe_operator/*
    (39 files)
    74

    View Slide

  75. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    $ ls Zend/tests/nullsafe_operator/
    001.phpt
    002.phpt
    003.phpt
    004.phpt
    005.phpt
    006.phpt
    007.phpt
    008.phpt
    009.phpt
    010.phpt
    011.phpt
    (省略)
    75
    主なphptテストファイル一覧
    029.phpt
    030.phpt
    031.phpt
    032.phpt
    033.phpt
    034.phpt
    035.phpt
    036.phpt
    037.phpt
    038.phpt
    039.phpt

    View Slide

  76. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    property書き込みシーンでの利用
    76
    Zend/tests/nullsafe_operator/004.phpt
    [テストケースから読み取れる仕様]
    ● プロパティの書き込み操作に対しては使用不可
    https://github.com/php/php-src/blob/9fa1d1330138ac424f990ff03e62721
    120aaaec3/Zend/tests/nullsafe_operator/004.phpt#L2

    View Slide

  77. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    Nullsafe operatorを怪しげなコード
    77
    Zend/tests/nullsafe_operator/041.phpt
    [テストケースから読み取れる仕様]
    ● ちょっとテクい事をしようとするPHPユーザー
    を想定したテストケースがある
    ● このケースでは undefined variable Warning
    が発生する
    https://github.com/php/php-src/blob/9fa1d1330138ac424f990ff03e62721
    120aaaec3/Zend/tests/nullsafe_operator/041.phpt#L2

    View Slide

  78. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    微妙なユーザーコードの動作をphptで理解する
    Nullsafe operatorを用いる際のPHPユーザーとし
    てやってしまいそうな微妙なコードがどう動くか
    についてphptから知った。
    「propertyの書き込み時に使っちゃうとどうな
    る?」
    78

    View Slide

  79. #phpcon © 2012-2020 BASE, Inc. 79
    Summary

    View Slide

  80. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    phpt を読むことで得られたもの
    phptを読むことで次の内容を理解できた。
    - 言語としてのエラーケース
    - 微妙なユースケースの仕様
    - 複数機能の組み合わせ
    - 開発者の実装背景
    - Cコードリーディングの出発点
    ドキュメントを読むだけではわからない・気が付
    かない内容を知れる。
    80

    View Slide

  81. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon 81
    PHPの新機能を見る際はphptと共に
    当発表のようにPHPのPull Requestを覗い
    て、phptファイルを探してみてください。
    「こういう書き方出来るようになったんだ〜」
    というPHPユーザーの視点から、
    「こういう振る舞いをこのパターンに気をつけ
    て実装したんだ」というPHP開発者の視点に、
    少しだけ近づける感覚が味わえるはずです。

    View Slide

  82. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    具体的な一歩目のガイド資料
    82
    PHP Advent Calendar DAY 5
    ソースコード(php-src)からPHPを
    ビルドする流れと仕組みを手を動かしながら理解する
    https://zenn.dev/hgsgtk/articles/fb9af8bfc64ec37bce2d
    PHP Advent Calendar DAY 9
    PHP8の新機能 Named Arguments を
    php-srcのテストコードから読む
    https://zenn.dev/hgsgtk/articles/461f3e8c1d81df

    View Slide

  83. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    PHP Internalを知る参考資料
    @hnwさん『Zend VMにおける例外の実装』 - 2020/02/11
    (https://www.slideshare.net/hnw/zend-vm-227589843)
    『Php internal architecture』 - 2016/10/19
    (https://www.slideshare.net/auroraeosrose/php-internal-architecture)
    @sji_chさん『PHP による hello world 入門』 - 2015/06/18
    (http://tech.respect-pal.jp/php-helloworld/)
    julien pauliさん『Quick tour of PHP from inside』 - 2012/06/07
    (https://www.slideshare.net/jpauli/quick-tour-of-php-from-inside)

    View Slide

  84. #phpcon © 2012-2020 BASE, Inc. 84
    Bonus

    View Slide

  85. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon 85
    Deep Dive into PHP Internal
    [テストケースから内部実装を覗く]
    ● Match expressionでは、Uncaught
    UnhandledMatchError: Unhandled match
    value of type %s in %s というエラーの発生があ
    りうる
    これに対応する実装はどうなっているのかな?
    Zend/tests/match/007.phpt

    View Slide

  86. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    https://github.com/php/php-src/blob/841b00f641d448f
    037c69f0910ec4fb54cd64b20/Zend/zend_vm_execute.h#
    L13836
    https://github.com/php/php-src/blob/841b00f641d448f
    037c69f0910ec4fb54cd64b20/Zend/zend_vm_execute.h#
    L13836
    Unhandled match value of type %s in %s
    “Unhandled match value of type”でgrepして見つける(3箇所ある)
    86
    zend_vm_def.h zend_vm_execute.h

    View Slide

  87. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon 87
    Cコードをいじってみてテストで確かめる
    ちょっとCコードを微修正してテストを走らせるとCコードレベルで理解する取っ掛か
    りになる
    $ make test TESTS='--show-diff Zend/tests/match/006.phpt'
    ========DIFF========
    001+ Fatal error: Uncaught UnhandledMatchError: b Unhandled match value
    of type bool in
    /Users/user/src/github.com/php/php-src/Zend/tests/match/006.php:3
    001- Fatal error: Uncaught UnhandledMatchError: Unhandled match value of
    type bool in %s
    ========DONE========
    FAIL Match expression with no cases [Zend/tests/match/006.phpt]

    View Slide

  88. © 2012-2019 BASE, Inc.
    © 2012-2020 BASE, Inc.
    #phpcon
    https://github.com/php/php-src/blob/841b00f641d448f
    037c69f0910ec4fb54cd64b20/Zend/zend_vm_execute.h#
    L13836
    https://github.com/php/php-src/blob/841b00f641d448f
    037c69f0910ec4fb54cd64b20/Zend/zend_vm_execute.h#
    L13836
    同じエラーだが実装が違う
    条件指定なし(006)・条件指定あるがマッチしない(007/037)で異なる
    88
    zend_vm_def.h
    zend_vm_execute.h

    View Slide

  89. #phpcon © 2012-2020 BASE, Inc. 89
    #track5-4-a-phpt

    View Slide