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を題材にします。

88964b936e864ca7d326272eaa70fa9a?s=128

Kazuki Higashiguchi

December 12, 2020
Tweet

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
  2. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon 当発表で得られるもの

    1 2 3 PHP8の新機能を理解できる PHP内部コードのテスト phpt の読 み方がわかる PHPの機能をドキュメントだけでなく、 テストコードから調べられるようになる 2
  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
  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
  5. #phpcon © 2012-2020 BASE, Inc. 5 “PHP Interpreter”の テスティングフレームワーク

  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
  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をビルドする流れと仕組みを手を動かしながら理解する』
  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%) ===================
  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ファイル件数
  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
  11. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon phptファイルの読み方

    --TEST-- テストタイトル --FILE-- テストの入力となるPHPスクリプト <?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
  12. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon phptファイルの「命名規則」

    phptファイルは命名規則が設定されている。 現実としてはすべてがこの規則に沿っているわけではないが、 どういった種類のテストがあるか傾向を知れる。 • bug<bugid>.phpt : Tests for bugs • <functionname>_basic.phpt : Tests for a function's basic behaviour • <functionname>_error.phpt : Tests for a function's error behaviour • <functionname>_variation.phpt : Tests for variations in a function's behaviour • <extname><no>.phpt : General tests for extensions https://qa.php.net/write-test.php#naming-conventions 12
  13. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon bug<bugid>.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
  14. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon <functionname>_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
  15. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon <functionname>_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
  16. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon <functionname>_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
  17. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon <extname><no>.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
  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
  19. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon 特定のテストを実行したい場合(make

    test) TESTSオプションに実行したいテストファイル名を指定する ディレクトリ以下全ケースの場合は<dir>/* (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)
  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)
  21. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon phpt

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

    New Features 22 1 2 3 Named Arguments 4 5 6 Constructor property promotion Attributes Union Types Match expression Nullsafe operator
  23. #phpcon © 2012-2020 BASE, Inc. 23 - PHP8 New Feature

    - Named Arguments
  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
  25. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon Named

    Arguments [Merits] 1. 引数が多い場合に順番を気にしなくてもよくなる 2. htmlspecialchars()のようにデフォルト値が多い引数の場合に記述が簡潔になる 3. 意味がわかりにくい引数を渡す場合のコードの自己記述性の向上 25
  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テストファイル一覧
  27. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon 基本的なテストケース

    27 Zend/tests/named_params/basic.phpt [テストケースから読み取れる仕様] • “positional argument”と”Named Argument”の併用が 可能 <?php test("A", "B", "C", e: "E", d: "D"); https://github.com/php/php-src/blob/d92229d8c78aac25925284e23aa790 3dca9ed005/Zend/tests/named_params/basic.phpt#L2
  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
  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
  30. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon 30

    Deep Dive into PHP Internal [テストケースから内部実装を覗く] • 重複して2回同じ引数に値を渡した 場合例外Errorが発生 ◦ Named parameter $%s overwrites previous argument これはどのような実装によって実現さ れているのか?
  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
  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
  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フェーズ
  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]
  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コードのエラーメッセージを 区別がつくように修正して テストを再実行した
  36. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon エラーケースの仕様をphptから理解する

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

    - Constructor property promotion
  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
  39. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon Constructor

    property promotion すべてのプロパティ属性に使用しなくてもいい。Constructorで渡す必要のない内部管理の 状態などと使い分け。 39
  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
  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
  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
  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
  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
  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
  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
  47. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon 微妙なユースケースについてphptで理解する

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

    - Attributes
  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)
  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
  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
  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
  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
  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
  55. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon 機能の組み合わせ可能性をphptで理解する

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

    - Union Types
  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
  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テストファイル一覧
  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
  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
  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
  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
  63. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon バリエーションに伴う仕様をphptで理解する

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

    - Match expression
  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
  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
  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
  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
  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
  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
  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
  72. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon 細かい挙動をphptで理解する

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

    - Nullsafe operator
  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
  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
  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
  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
  78. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon 微妙なユーザーコードの動作をphptで理解する

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

  80. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. #phpcon phpt

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

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

  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
  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
  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]
  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
  89. #phpcon © 2012-2020 BASE, Inc. 89 #track5-4-a-phpt