Skip to content

THRIFT-2950: Fix PHP scalar set serialization - #3787

Open
sveneld wants to merge 1 commit into
apache:masterfrom
sveneld:THRIFT-2950
Open

THRIFT-2950: Fix PHP scalar set serialization#3787
sveneld wants to merge 1 commit into
apache:masterfrom
sveneld:THRIFT-2950

Conversation

@sveneld

@sveneld sveneld commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Accept scalar PHP sets passed as sequential lists without breaking legacy keyed-set input.
  • Apply the compatibility fix in generated PHP serialization and shared runtime helpers.
  • Add regression coverage for generated JSON serialization and TBase/TException round-trips.
  • Exercise empty and non-empty list-form sets in the shared PHP cross-test client, including negative and non-consecutive values. Verify the returned legacy keyed-set representation without depending on element order; retain the existing legacy-input cross-test.

Testing

  • Targeted PHP unit and integration tests for TBase, TException, TJSONProtocol, TProtocolInlined, JsonSerialize, Validator, and ThriftClassLoader were previously verified on this branch.
  • New cross-tests: PHP client against C++ and Python servers with buffered transport, using Binary, Compact, and JSON protocols (six successful client/server runs).
  • Before regenerating PHP classes with the fixed compiler, all six runs fail on the new non-empty inputs: values are replaced by array indexes. Regenerating with the THRIFT-2950 compiler makes all six pass.
  • PHP syntax check and git diff whitespace check pass. PHPCS reports no errors and two existing warnings outside the added block (mixed declarations/side effects and an existing long line).

Generated-by: OpenAI Codex GPT-5 noreply@openai.com

@sveneld
sveneld marked this pull request as ready for review September 2, 2026 18:13
Copilot AI lite review requested due to automatic review settings September 2, 2026 18:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new array_is_list()-based detection can misclassify legacy keyed-set inputs with sequential element keys (e.g. {0,1}), causing incorrect serialization in both runtime and generated code.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the PHP serializer (both generated PHP code and the shared runtime helpers) to accept scalar Thrift set<> values provided as sequential PHP lists, while adding regression tests for TBase/TException round-trips and JSON protocol output.

Changes:

  • Accept sequential PHP arrays (e.g. [10, 20]) as scalar-set inputs during serialization.
  • Apply the same compatibility logic in both TBase and TException runtime writers and the PHP code generator.
  • Add unit/integration coverage for sequential set inputs (TBase, TException, TJSONProtocol).
File summaries
File Description
lib/php/test/Unit/Lib/Exception/TExceptionTest.php Adds a unit test asserting round-trip behavior when a set is provided as a sequential list.
lib/php/test/Unit/Lib/Base/TBaseTest.php Adds a unit test asserting round-trip behavior when a struct set field is provided as a sequential list.
lib/php/test/Integration/Lib/Protocol/TJSONProtocolTest.php Adds an integration test asserting JSON serialization output for a sequential-list set input.
lib/php/lib/Exception/TException.php Updates set/list writing logic to optionally serialize set values for sequential arrays.
lib/php/lib/Base/TBase.php Updates set/list writing logic to optionally serialize set values for sequential arrays.
compiler/cpp/src/thrift/generate/t_php_generator.cc Updates generated scalar-set serialization to choose between iterating keys vs values based on list-ness.
Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread compiler/cpp/src/thrift/generate/t_php_generator.cc
Comment thread lib/php/lib/Base/TBase.php Outdated
Comment thread lib/php/lib/Exception/TException.php Outdated
Comment thread lib/php/test/Unit/Lib/Base/TBaseTest.php
Copilot AI review requested due to automatic review settings September 2, 2026 19:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new list-vs-legacy heuristic introduces an unresolved ambiguity for set<bool> (e.g., [true]) that needs an explicit behavior decision plus tests/docs to match the PR’s stated compatibility goal.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread compiler/cpp/src/thrift/generate/t_php_generator.cc
Comment thread lib/php/lib/Base/TBase.php
Comment thread lib/php/lib/Exception/TException.php
Copilot AI review requested due to automatic review settings September 3, 2026 06:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The runtime and generator changes are consistent with each other and are backed by targeted unit/integration regression tests covering the key compatibility and ambiguity cases.

Review details
  • Files reviewed: 8/8 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Legacy keyed string-set serialization still passes uncast keys in TBase and TException.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (2)

lib/php/lib/Base/TBase.php:368

  • The legacy-marker branch still passes the raw PHP array key to the typed protocol writer. A valid legacy set<string> such as ['0' => true] is stored by PHP with integer key 0, so writeString() throws under strict_types=1; the generated serializer already recasts set keys to their declared scalar type. Cast the selected legacy key according to $etype before dispatch, not only for BOOL.
            $elem = $set && !$setUsesValues ? $key : $val;
            if ($set && !$setUsesValues && $etype === TType::BOOL) {
                $elem = (bool) $elem;

lib/php/lib/Exception/TException.php:368

  • The legacy-marker branch still passes the raw PHP array key to the typed protocol writer. A valid legacy set<string> such as ['0' => true] is stored by PHP with integer key 0, so writeString() throws under strict_types=1; the generated serializer already recasts set keys to their declared scalar type. Cast the selected legacy key according to $etype before dispatch, not only for BOOL.
            if ($set && !$setUsesValues && $etype === TType::BOOL) {
                $elem = (bool) $elem;
            }
  • Files reviewed: 8/8 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment on lines +2707 to +2710
if (elem_type->is_bool()) {
indent(out) << "if (!$" << set_uses_values << ") {" << '\n';
indent_up();
indent(out) << "$" << iter_elem << " = (bool) $" << iter_elem << ";" << '\n';
@sveneld
sveneld marked this pull request as draft September 11, 2026 09:27
@sveneld
sveneld marked this pull request as ready for review September 13, 2026 08:41
Copilot AI review requested due to automatic review settings September 13, 2026 08:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Resolve typedefs before checking for boolean element types in generated set serialization.

Review details

Suppressed comments (1)

compiler/cpp/src/thrift/generate/t_php_generator.cc:2707

  • elem_type can be a typedef, but t_typedef does not override is_bool(). For typedef bool Flag; set<Flag>, the ambiguous legacy form such as [true] therefore skips the cast and the generated strict-types code passes the integer PHP key (0) to writeBool(bool), causing a TypeError. Resolve the type before checking is_bool() so typedef-based bool sets follow the same compatibility path.
      if (elem_type->is_bool()) {
  • Files reviewed: 9/9 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 13, 2026 13:31
@sveneld

sveneld commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the bool typedef review concern with generated-code coverage and simplification. New fixtures cover set, set (typedef bool), and a chained typedef for sequential values, legacy keyed values, ambiguous [true], and legacy true. These tests also passed before this follow-up: generate_serialize_set_element() already calls emit_array_key_recast(), which resolves typedefs and emits the bool cast. The reported TypeError was therefore not reproducible on the current branch. Removed the redundant bool-only branch instead of adding a second typedef-aware cast. Inspected regenerated PHP: all three fields cast before writeBool(). Targeted unit/integration suite: 177 tests, 336 assertions, exit 0 (2 PHPUnit deprecations); PHPCS and git diff --check pass.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Moderate issues remain in TBase and TException for legacy string/UUID keyed sets under strict typing.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 10/10 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread lib/php/lib/Base/TBase.php Outdated
Comment thread lib/php/lib/Exception/TException.php Outdated
Client: php

Generated-by: OpenAI Codex GPT-5 <noreply@openai.com>
Copilot AI review requested due to automatic review settings September 13, 2026 14:32
@sveneld

sveneld commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Fixed the accelerated cross-test failures as well: the native PHP extension still serialized only keys for scalar sets. It now uses the same list-versus-all-true-marker rule as the PHP implementation. Added scalar_sets.phpt comparing native wire output with explicitly written expected Binary messages; before the change it failed for integer, string, and bool lists. Verification: 179 targeted PHP tests / 342 assertions, all 4 extension PHPT tests, and accelerated PHP clients against C++ and Python servers over buffered, framed, and HTTP transports all pass (6 cross-test runs). PHPCS and git diff --check pass. Repository-wide make style remains blocked by stale local Autotools files referencing the removed Swift directory. Previous local cross-test validation covered only the non-accelerated path; this follow-up closes that gap. CI needs to run again for the full matrix.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Add inline-mode coverage that verifies the serializer emits actual non-consecutive set elements.

Review details

Suppressed comments (1)

compiler/cpp/src/thrift/generate/t_php_generator.cc:2685

  • The updated set loop also changes the binary_inline_ serializer, but the existing inlined test only writes newset and then reads it with the older V1 schema, so that field is skipped and an implementation that still serialized indexes would pass. Add an inline-mode assertion or round-trip that inspects the emitted set elements, including a non-consecutive list value.
    if (php_is_scalar(elem_type)) {
  • Files reviewed: 12/12 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants