Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type trees #7

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open

type trees #7

wants to merge 19 commits into from

Conversation

withinboredom
Copy link

@withinboredom withinboredom commented Mar 28, 2025

Summary by CodeRabbit

  • New Features

    • Introduced an enhanced type representation system that supports complex type definitions, including unions and intersections, leading to more robust type checking and error handling.
    • Added a new function for freeing interned type trees during the shutdown process.
    • Updated argument metadata to include additional details for clearer definition and handling.
  • Bug Fixes

    • Streamlined the type-checking process by removing unnecessary caching mechanisms.
  • Refactor

    • Overhauled type normalization and verification processes for better performance and maintainability.
  • Style

    • Made minor formatting improvements for enhanced readability.
  • Tests

    • Adjusted internal test definitions to align with the updated type structures.

Copy link

coderabbitai bot commented Mar 28, 2025

Walkthrough

The changes integrate interned type trees into the Zend Engine’s type handling process. Internal APIs now utilize a new structure and associated functions to normalize and compare complex type information. Several function signatures and macros have been updated across compilation, execution, and JIT helper modules to include a new type tree parameter. Additionally, minor formatting and readability improvements have been applied.

Changes

Files Change Summary
Zend/zend_API.c, Zend/zend_API.h, Zend/zend_types.h Integrated interned type trees into type normalization by introducing new functions (e.g., zend_type_to_interned_tree) and a new zend_type_node structure along with an added enum. Macros were updated to include an extra NULL field.
Zend/zend_compile.c, Zend/zend_compile.h, Zend/zend_execute.c, Zend/zend_execute.h, Zend/zend_vm_def.h, Zend/zend_vm_execute.h, ext/opcache/jit/zend_jit_helpers.c Updated function signatures and internal type checking logic to pass and utilize the new type_tree parameter, enhancing type matching and verification.
ext/zend_test/test.c Updated argument info definitions to accommodate an additional field.
Zend/zend.c Added a call to zend_type_free_interned_trees() in the zend_shutdown() function for cleanup during shutdown.
Zend/zend_execute_API.c, Zend/zend_globals.h, ext/opcache/ZendAccelerator.c Introduced new members and updated initialization logic to accommodate the handling of type trees in global states.

Sequence Diagram(s)

sequenceDiagram
    participant Caller as Compiler/Registrar
    participant Norm as zend_normalize_internal_type
    participant Converter as zend_type_to_interned_tree
    participant Executor as zend_check_type_slow
    participant Checker as zend_type_node_matches

    Caller->>Norm: Normalize type information
    Norm->>Converter: Convert zend_type to interned type tree
    Converter-->>Norm: Return interned tree
    Norm-->>Caller: Provide normalized type_tree
    Caller->>Executor: Call function with type_tree
    Executor->>Checker: Validate type match using interned tree
    Checker-->>Executor: Return matching result
Loading

Poem

In digital fields where our types align,
I hop through trees with a code so fine.
Interned branches craft a structure so new,
Guiding each check like morning dew.
With carrot code and a hop so clear, 🥕
This rabbit cheers for progress near!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (4)
Zend/zend_API.c (2)

2901-2901: Consider concurrency protections for the global static pointer.

Declaring this file-wide static HashTable *interned_type_tree could introduce concurrency issues in multi-threaded environments, as multiple threads might access or modify it without synchronization.


2903-2909: Check for potential integer overflow and reallocation overhead.

The macro ADD_TO_TREE repeatedly grows the array via erealloc. While simple, this could be costly if invoked in a large loop. Also ensure that (count + 1) multiplication by sizeof(zend_type) can’t overflow.

Zend/zend_execute.c (2)

1143-1172: Clarify the numeric return codes in zend_type_node_matches.

Currently, zend_type_node_matches returns 0 for a mismatch, 1 for a match, and 2 to indicate “fallback to old logic” for simple types. These magic numbers might confuse future maintainers or lead to subtle bugs. Consider using an enum or well-named constants to express these outcomes more explicitly.


1174-1184: Use a symbolic constant instead of result < 2.

In zend_check_type_slow, the check for result < 2 relies on the special “2” code from zend_type_node_matches. Replacing it with a symbolic constant or a clear enumerated type might enhance readability and reduce the risk of errors if more return values are introduced in the future.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0943b8b and 429bb82.

📒 Files selected for processing (11)
  • Zend/zend_API.c (4 hunks)
  • Zend/zend_API.h (6 hunks)
  • Zend/zend_compile.c (3 hunks)
  • Zend/zend_compile.h (3 hunks)
  • Zend/zend_execute.c (7 hunks)
  • Zend/zend_execute.h (1 hunks)
  • Zend/zend_types.h (1 hunks)
  • Zend/zend_vm_def.h (1 hunks)
  • Zend/zend_vm_execute.h (5 hunks)
  • ext/opcache/jit/zend_jit_helpers.c (2 hunks)
  • ext/zend_test/test.c (1 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
Zend/zend_API.c (2)
Zend/zend_compile.h (3)
  • type (933-933)
  • type (1011-1011)
  • name (991-991)
Zend/zend_API.h (1)
  • type (451-451)
Zend/zend_execute.c (2)
Zend/zend_compile.h (2)
  • type (933-933)
  • type (1011-1011)
Zend/zend_execute.h (1)
  • zend_check_user_type_slow (107-108)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: WINDOWS_X64_ZTS
  • GitHub Check: MACOS_ARM64_DEBUG_NTS
  • GitHub Check: LINUX_X64_DEBUG_ZTS_ASAN
  • GitHub Check: BENCHMARKING
  • GitHub Check: LINUX_X64_RELEASE_NTS
  • GitHub Check: LINUX_X32_DEBUG_ZTS
  • GitHub Check: FREEBSD
🔇 Additional comments (34)
Zend/zend_vm_execute.h (5)

10806-10806: Consistent update for type checking mechanism.

The change replaces &ret_info->type with ret_info->type_tree in the call to zend_check_type_slow(). This aligns with the PR's goal of integrating interned type trees into the Zend Engine's type handling process.


21543-21543: Consistent update for type checking mechanism.

The same pattern of replacing &ret_info->type with ret_info->type_tree is applied here, maintaining consistency with other changes in the file.


30023-30023: Consistent update for type checking mechanism.

This change follows the same pattern of updating the zend_check_type_slow() call to use the new type tree structure.


37817-37817: Consistent update for type checking mechanism.

The change here matches the pattern seen in previous hunks, ensuring consistent implementation across the codebase.


50618-50618:

✅ Verification successful

Consistent update for type checking mechanism.

The final instance of this change maintains consistency with all previous updates to the zend_check_type_slow() function calls.


🏁 Script executed:

#!/bin/bash
# Verify that all instances of zend_check_type_slow have been updated consistently across the codebase

# Search for any remaining instances of calls with the old parameter pattern
echo "Checking for any missed updates to zend_check_type_slow calls..."
rg "zend_check_type_slow\(\s*&[^,]+->type\s*," --type cpp

Length of output: 1028


Consistent update for type checking mechanism confirmed.

The grep output verifies that all calls to zend_check_type_slow()—including the final instance in Zend/zend_vm_execute.h and the related usage in Zend/zend_vm_def.h—consistently use the updated parameter pattern (i.e. passing &ret_info->type). No outdated invocations were detected.

Zend/zend_vm_def.h (1)

4430-4433:

❓ Verification inconclusive

Confirm consistent usage of the new parameter.
The newly introduced ret_info->type_tree usage appears correct for advanced type verification. However, please verify that every call site of zend_check_type_slow() in the codebase has been updated to include the new parameter, ensuring consistent type checks and avoiding potential compile or runtime errors.

Use this script to find and examine all zend_check_type_slow() calls:


🏁 Script executed:

#!/bin/bash
# Search for all zend_check_type_slow calls for verification
rg -A 3 "zend_check_type_slow("

Length of output: 126


Manual Verification Required: Confirm Updates to zend_check_type_slow Calls

The change in Zend/zend_vm_def.h (lines 4430–4433) correctly introduces the new ret_info->type_tree parameter for advanced type verification. However, the automated search for all instances of zend_check_type_slow( failed due to a regex parse error. To ensure consistent usage across the codebase, please verify manually that every call to zend_check_type_slow() has been updated with the new parameter.

For improved verification, try running this corrected shell command:

#!/bin/bash
# Search for all zend_check_type_slow calls using proper regex escaping
rg -A 3 "zend_check_type_slow\\("

Review the output for any call sites that may need updating.

ext/zend_test/test.c (1)

1205-1205: Updated structure to include new type_tree field.

The code now includes an additional NULL parameter in the arginfo_zend_test_internal_dnf_arguments array. This change aligns with modifications in Zend/zend_compile.h where a new member, zend_type_node *type_tree, has been added to the zend_internal_arg_info structure to support interned type trees.

Zend/zend_types.h (1)

145-164: Added new type tree structure for enhanced type representation.

The addition of the zend_type_node structure and zend_type_node_kind enum creates a foundational construct for representing complex types. This structure allows for:

  1. Simple types via the simple_type field
  2. Union types via the compound structure with ZEND_TYPE_UNION kind
  3. Intersection types via the compound structure with ZEND_TYPE_INTERSECTION kind

This change enables more efficient handling of complex type information throughout the Zend Engine by creating a hierarchical tree representation of types.

Zend/zend_compile.c (3)

7351-7351: Improved code readability with proper spacing.

Adding a blank line here improves the visual separation between logical blocks of code, enhancing readability.


7588-7588: Correctly implementing interned type trees for return types.

This addition properly populates the type_tree field by converting the zend_type to an interned tree structure for return type information. This aligns with the PR's objective of integrating interned type trees into the type handling process.


7835-7836: Good practice: Added whitespace and implemented type tree conversion for parameters.

The added blank line improves code readability, and the new line correctly populates the type_tree field for parameter information by converting zend_type to an interned tree structure. This is consistent with the implementation for return types.

Zend/zend_execute.h (1)

107-108:

✅ Verification successful

API signature updated to support interned type trees.

The function signature for zend_check_user_type_slow has been modified to include an additional parameter zend_type_node *type_tree. This change aligns with the broader integration of interned type trees into the Zend Engine's type handling process as described in the PR.


🏁 Script executed:

#!/bin/bash
# Check for other occurrences of this function to ensure consistent signature changes
rg -A 1 -B 1 "zend_check_user_type_slow" --type c --type h

Length of output: 1136


API signature modification verified for zend_check_user_type_slow

The new parameter zend_type_node *type_tree has been consistently applied:

  • Declaration in Zend/zend_execute.h
  • Definition in Zend/zend_execute.c
  • All call sites (e.g., in ext/opcache/jit/zend_jit_helpers.c) now correctly pass the additional parameter

No further changes are needed.

ext/opcache/jit/zend_jit_helpers.c (2)

1904-1905: Additional type_tree parameter added correctly.

The new arg_info->type_tree parameter has been properly added to zend_check_user_type_slow which aligns with the PR objective of integrating interned type trees into the Zend Engine's type handling.


1921-1922: Additional type_tree parameter added correctly.

Similar to the previous change, the arg_info->type_tree parameter has been appropriately added to zend_check_user_type_slow in the return type verification function. This maintains consistency in the type checking implementation.

Zend/zend_compile.h (4)

455-455: Type tree field added to zend_property_info structure

The addition of the zend_type_node *type_tree field enhances the type representation for class properties. This complements the existing zend_type type field by providing a more structured representation of complex types.


483-483: Type tree field added to zend_internal_arg_info structure

The type_tree field has been added to the internal function argument information structure, providing a more comprehensive way to represent parameter types for internal functions.


491-491: Type tree field added to zend_arg_info structure

This change mirrors the addition of the type_tree field to the user function argument information structure, maintaining consistency with the internal function equivalent.


503-503: Type tree field added to zend_internal_function_info structure

The type_tree field has been added to the internal function information structure, completing the updates to all relevant type-containing structures. This consistent approach ensures that return types can be represented with the same fidelity as parameter and property types.

Zend/zend_API.c (5)

2967-3001: Hash function looks good.

The custom FNV-1a hashing of zend_type_node components appears correct and consistent with typical usage.


3002-3044: Equality check implementation looks valid.

Comparing type masks, optional names, and recursively comparing compound type arrays appears logically sound.


3116-3140: Normalization logic is reasonable.

Interning type names and converting them into an interned tree is consistent with the approach in the rest of the code. No immediate concerns.


4885-4887: Approach for persistent vs. non-persistent classes looks consistent.

Using zend_normalize_internal_type() for persistent classes and zend_type_to_interned_tree() otherwise fits the pattern seen in other parts of the code for memory and type management.


2941-2966:

❓ Verification inconclusive

Verify absence of cyclical references in compound type comparisons.

The recursive calls to compare sub-type nodes could, in theory, risk infinite recursion if there were cyclical references. Ensure there's no cycle creation logic (e.g. by userland code) that might cause an infinite loop.


🏁 Script executed:

#!/bin/bash
# Attempt to locate potential cycles in type node usage by scanning for suspicious aliases or repeated references.
# This is a heuristic approach that looks for repeated references in any union/intersection initialization.
rg "zend_type (.*)=.*(ZEND_TYPE_UNION|ZEND_TYPE_INTERSECTION)" -A 10

Length of output: 70


Attention: Manual verification recommended for cyclical reference safeguards in compound type comparisons.

The recursive logic in compare_type_nodes appears to work as intended by iterating over the compound.types array. However, since the heuristic search for union/intersection initializations did not yield results, it’s advisable to manually verify that the compound type creation logic (e.g., for ZEND_TYPE_UNION and ZEND_TYPE_INTERSECTION) enforces conditions that prevent cyclical references. Specifically, ensure that:

  • Type node constructions do not introduce self-references or indirect cycles.
  • The initialization routines for compound types are designed to preclude infinite recursion.

Please review the compound type creation code (likely within the type construction or initialization modules) to confirm that cycle creation is explicitly prevented.

Zend/zend_API.h (7)

131-165: Well-structured addition of type node field to argument information macros

The changes consistently add a NULL field to all argument information macros. This additional field appears to be for the new interned type tree structure, which will enhance PHP's type handling capabilities by normalizing and efficiently comparing complex type information.


170-170: Consistent format update to return type information macro

The ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX2 macro is updated with the same NULL field pattern as the other argument information macros, maintaining consistency across the codebase.


183-183: Consistent addition of NULL field for return type mask

The ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX2 macro is updated to include the new NULL field, consistent with the pattern established in other macros.


193-193: Consistent implementation for object type mask information

The macro for object type mask information now includes the NULL field for the interned type tree, maintaining consistency with other related macros.


203-203: Type information macro properly updated

The ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX2 macro is correctly modified to include the NULL field for storing interned type tree information.


216-216: Standard argument info macro correctly updated

The basic argument info macro is properly updated to include the NULL field, completing the consistent pattern of updates across all argument information macros.


451-452: New function added for type tree internment

A new API function zend_type_to_interned_tree() has been added to convert zend_type to an interned tree structure. This function is a key component of the new type handling mechanism, allowing for normalized representation and efficient comparison of complex type information.

Zend/zend_execute.c (4)

1194-1194: Initialization approach looks fine.

The addition of the line initializing type_mask with ZEND_TYPE_FULL_MASK(*type) appears correct and consistent with existing usage patterns for type masking.


1222-1237: Top-level logic remains coherent.

Wrapping the new type_tree parameter into zend_check_type maintains the existing logic flow, and delegating to zend_check_type_slow when necessary is consistent with the intended refactor. No correctness issues identified.


1241-1245: Consistency with zend_check_type_slow usage.

Ensuring zend_check_user_type_slow simply passes the type_tree to zend_check_type_slow with is_internal set to false aligns well with the broader design. The approach here is succinct and appears correct.


1255-1268:

✅ Verification successful

Verify type_tree non-null usage at runtime.

Where ZEND_TYPE_IS_SET(cur_arg_info->type) triggers a call to zend_check_type(&cur_arg_info->type, cur_arg_info->type_tree, ...), confirm that type_tree is indeed non-null in all cases. If any code path updates type_tree after compilation, a safety check or assertion might be warranted to avoid potential null-pointer scenarios.

Please run a script to search for assignments to arg_info->type_tree throughout the codebase, ensuring it’s always initialized before these call paths:


🏁 Script executed:

#!/bin/bash
# Verify that type_tree is set prior to usage in zend_check_type calls
rg "arg_info(\.|\->)type_tree\s*=" -A 5

Length of output: 391


Type Tree Safety Verified

The verification confirms that arg_info->type_tree is always initialized via the call to zend_type_to_interned_tree(arg_info->type) in Zend/zend_compile.c. There is no evidence of any code path where type_tree goes uninitialized before being used in zend_check_type. No additional runtime check is necessary.

@withinboredom withinboredom changed the title @rabbitai type trees Mar 28, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
Zend/zend_types.h (1)

817-821: Helper macro for type tree manipulation

This macro provides a convenient way to dynamically add types to a type list, handling the memory reallocation. It's a useful utility for building type trees.

Consider adding a comment explaining that this macro handles the memory reallocation for the list.

 #define ADD_TO_TYPE_TREE(list, count, value) \
 do { \
+    /* Reallocate memory for the type list and add the new value */ \
     list = erealloc(list, sizeof(zend_type) * (count + 1)); \
     list[count++] = value; \
 } while (0)
Zend/zend_API.c (2)

3066-3116: Proactive flattening and deduplication.

This function merges child types of the same kind and deduplicates them before interning. The approach is correct. As a potential optimization, if there's only one unique child, you could skip building an extra compound node.

+ // (Optional) Example: If deduped_count == 1, directly reuse the single child node

4886-4889: Unify or clarify function usage.

For persistent classes, zend_normalize_internal_type() is called, otherwise zend_type_to_interned_tree() is used. Both paths ultimately produce interned trees. Consider merging these paths to avoid subtle divergences or unify them into a single utility function, keeping the logic simpler.

- property_info->type_tree = zend_normalize_internal_type(&property_info->type);
...
- property_info->type_tree = zend_type_to_interned_tree(property_info->type);
+ // unify into a single function call that detects persistent vs non-persistent usage internally
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 429bb82 and 6f1e1d2.

📒 Files selected for processing (4)
  • Zend/zend.c (1 hunks)
  • Zend/zend_API.c (4 hunks)
  • Zend/zend_API.h (6 hunks)
  • Zend/zend_types.h (2 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
Zend/zend.c (1)
Zend/zend_API.h (1)
  • zend_type_free_interned_trees (452-452)
Zend/zend_API.c (4)
Zend/zend_types.h (2)
  • void (1364-1369)
  • void (1371-1376)
Zend/zend_compile.h (3)
  • type (933-933)
  • type (1011-1011)
  • name (991-991)
Zend/zend_execute.h (4)
  • name (37-37)
  • name (51-51)
  • name (52-52)
  • name (421-421)
Zend/zend_execute.c (2)
  • HashTable (2366-2380)
  • HashTable (4789-4865)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: WINDOWS_X64_ZTS
  • GitHub Check: MACOS_ARM64_DEBUG_NTS
  • GitHub Check: LINUX_X64_DEBUG_ZTS_ASAN
  • GitHub Check: LINUX_X32_DEBUG_ZTS
  • GitHub Check: LINUX_X64_RELEASE_NTS
  • GitHub Check: FREEBSD
  • GitHub Check: BENCHMARKING
🔇 Additional comments (17)
Zend/zend.c (1)

1198-1198: Well-placed cleanup call for the new type tree system

The addition of zend_type_free_interned_trees() in the shutdown sequence ensures proper cleanup of interned type trees during engine shutdown. This is appropriately placed after other subsystem cleanups like attributes shutdown but before final memory management operations.

Zend/zend_types.h (3)

145-146: Forward declaration of new type tree structure

A clean forward declaration of the new type node structure that will be used for the type tree system.


147-151: Good enumeration for type node variants

The enumeration clearly identifies the three possible kinds of type nodes (simple, union, and intersection) which aligns well with PHP's type system capabilities.


153-164: Well-structured type node implementation

The zend_type_node structure is well designed with:

  1. A discriminator (kind) to determine the node type
  2. A union that efficiently represents either simple types or compound types
  3. For compound types, a clean structure with count and array of child nodes

This design allows for recursive representation of complex type expressions.

Zend/zend_API.h (7)

131-165: Systematic update to all argument info macros to include type tree support.

All the argument information structure macros have been updated to include an additional NULL field for each definition. This change adds support for interned type trees, which provides a more structured approach to handling complex type information in the Zend Engine.

This consistent pattern of changes affects the following macro categories:

  • Basic argument info macros (ZEND_ARG_INFO, etc.)
  • Type-specific argument macros (ZEND_ARG_TYPE_INFO, etc.)
  • Object and class-related macros (ZEND_ARG_OBJ_INFO, etc.)
  • Special purpose macros (ZEND_ARG_ARRAY_INFO, ZEND_ARG_CALLABLE_INFO)

170-170: Consistent extension of return type info macros for type tree support.

The return object info macro has been updated with the same NULL parameter pattern as argument info macros, maintaining consistency throughout the type system.


183-183: Type mask return info macro updated to match the new type tree schema.

The return type mask macro follows the same modification pattern as the other argument and return type macros, adding support for interned type trees.


193-193: Object type mask return info macro updated for type tree compatibility.

This complex return type macro now includes the additional NULL field, ensuring all parts of the type system are consistently updated.


203-203: Return type info macro aligned with the new type tree structure.

The return type info macro now has the same structure as other macro definitions, maintaining consistency across the type system modifications.


216-216: General argument info macro updated with type tree support.

The base argument info macro has been updated to follow the consistent pattern of including the additional NULL field for interned type trees.


451-453:

✅ Verification successful

New type tree API functions added.

Two new functions have been introduced:

  1. zend_type_to_interned_tree() - Converts a zend_type to an interned type tree structure
  2. zend_type_free_interned_trees() - Deallocates interned type trees

These functions are essential parts of the type tree integration, providing the ability to convert types to tree structures and properly clean up resources during shutdown.


🏁 Script executed:

#!/bin/bash
# Verify that these functions are called in the codebase to ensure proper usage and cleanup

echo "Checking zend_type_to_interned_tree usage in the codebase:"
rg "zend_type_to_interned_tree" --type c --type h

echo -e "\nChecking zend_type_free_interned_trees usage in the codebase:"
rg "zend_type_free_interned_trees" --type c --type h

Length of output: 1137


Confirmed: New type tree API functions usage verified

The two new functions introduced—zend_type_to_interned_tree() and zend_type_free_interned_trees()—are being used appropriately across the codebase. The function conversion is leveraged in compilation routines (e.g., in Zend/zend_compile.c) and the cleanup function is correctly invoked during shutdown (e.g., in Zend/zend.c).

  • zend_type_to_interned_tree() is called in multiple locations (e.g., Zend/zend_compile.c and Zend/zend_API.c), ensuring conversion of type information to the interned type tree.
  • zend_type_free_interned_trees() has its definition and usage confirmed (e.g., Zend/zend_API.c and Zend/zend.c), ensuring proper deallocation during shutdown.

These validations confirm that the changes are in line with the intended design and usage, and no additional modifications are needed.

Zend/zend_API.c (6)

2911-2940: Duplicate pointer-based string comparison issue.

This logic compares string pointers (line 2925) rather than string content, which can falsely classify distinct but content-identical strings as different. This concern was previously raised in a past review comment. Instead of checking pointer equality (ZSTR_VAL(a_name) == ZSTR_VAL(b_name)), consider using zend_string_equals() or a similar safe comparison method.

- const int cmp = ZSTR_VAL(a_name) == ZSTR_VAL(b_name);
- if (cmp != 0) {
-     return cmp;
- }
+ const int cmp = zend_string_compare(a_name, b_name);
+ if (cmp != 0) {
+     return (cmp < 0) ? -1 : 1;
+ }

2942-2966: Looks clean and consistent.

The function correctly orders type nodes by kind, then either delegates to compare_simple_types for simple types or compares compound arrays for unions/intersections. This provides a clear ordering for complex type sets.


2968-3002: Hashing strategy seems reasonable.

Using the FNV-1a hash for the node kind, type mask, and each child is a sound choice. Ensure that collisions are handled by equality checks, which you already do in zend_type_node_equals.


3003-3044: Equality check for type nodes is well-structured.

The function consistently checks the kind, compares masks/names for simple types, and recursively checks union/intersection children. This thorough approach should guarantee accurate equality results.


3117-3141: Good handling of literal and list-based internal types.

This function normalizes named types into interned strings, then delegates to zend_type_to_interned_tree(). The assertion to disallow “resource” within type masks is helpful. Consider gracefully skipping or warning for any unexpected type codes in production builds instead of asserting.


3046-3065:

❓ Verification inconclusive

Potential concurrency concern.

intern_type_node() reuses or inserts nodes into the global interned_type_tree hashtable. If this code can be invoked in parallel, it could cause data races. If Zend is single-threaded or tokens are locked beforehand, it may be fine; otherwise, add synchronization.


🏁 Script executed:

#!/bin/bash
# Investigate how/where `intern_type_node` is invoked to check for parallel usage
rg 'intern_type_node' -A 10

Length of output: 1684


Concurrency impact review – verification required

Based on the search results, all usages of intern_type_node() appear within the same file (with one instance showing recursive invocation), and there is no direct evidence from this search that it’s concurrently invoked from multiple threads. However, given that intern_type_node() accesses and modifies the global interned_type_tree without any synchronization, it remains important to ensure that this code is only ever executed in a single-threaded context—or, if Zend’s thread-safe (ZTS) build is enabled and concurrent access is possible, to add appropriate locking around these operations.

  • Current observations:

    • The function is used recursively within Zend/zend_API.c.
    • No explicit parallel invocations were identified in our search output.
  • Action Item:
    Verify that either (a) the execution context guarantees single-threaded access (or that external synchronization is already applied), or (b) introduce synchronization mechanisms (e.g., mutex locks) for thread-safe builds.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f1e1d2 and 50e3ac9.

📒 Files selected for processing (1)
  • Zend/zend_API.c (4 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
Zend/zend_API.c (4)
Zend/zend_types.h (2)
  • void (1364-1369)
  • void (1371-1376)
Zend/zend_compile.h (3)
  • type (933-933)
  • type (1011-1011)
  • name (991-991)
Zend/zend_execute.h (4)
  • name (37-37)
  • name (51-51)
  • name (52-52)
  • name (421-421)
Zend/zend_execute.c (2)
  • HashTable (2366-2380)
  • HashTable (4789-4865)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: MACOS_ARM64_DEBUG_NTS
  • GitHub Check: WINDOWS_X64_ZTS
  • GitHub Check: LINUX_X64_DEBUG_ZTS_ASAN
  • GitHub Check: BENCHMARKING
  • GitHub Check: LINUX_X64_RELEASE_NTS
  • GitHub Check: FREEBSD
  • GitHub Check: LINUX_X32_DEBUG_ZTS
🔇 Additional comments (8)
Zend/zend_API.c (8)

2911-2940: LGTM: Well-structured type comparison function.

The function logic correctly handles comparison of simple types by checking type mask, class names, and nullable flags in a consistent order.


2942-2966: LGTM: Recursive type node comparison follows standard patterns.

The comparison function correctly handles both simple and compound types, with proper recursion for compound types.


2968-3001: LGTM: Robust hashing algorithm for type nodes.

The implementation uses FNV-1a hashing algorithm with appropriate handling of different node types and recursive hashing for compound types.


3003-3044: LGTM: Type node equality check is thorough.

The function properly handles pointer equality as an optimization and correctly compares all node properties.


3046-3065: Add locking mechanism to prevent data races.

The intern_type_node function modifies the global interned_type_tree without any synchronization, which could lead to race conditions in multi-threaded environments. Consider implementing a mutex lock for thread safety.


3066-3115: LGTM: Convert zend_type to interned tree with deduplication.

The function handles null check, simple types, and compound types correctly. Additionally, it performs sorting and deduplication of child types, which is important for normalization.


3117-3142: LGTM: Updated to return the interned tree.

The function has been properly modified to return a zend_type_node* pointer to the interned tree after normalizing the internal type.


4884-4889: LGTM: Proper type tree initialization in property declaration.

The code correctly initializes the property's type_tree field based on whether the class is a persistent internal class, ensuring proper type representation.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9896c3b and c18a585.

📒 Files selected for processing (2)
  • Zend/zend_API.c (4 hunks)
  • Zend/zend_types.h (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
Zend/zend_API.c (3)
Zend/zend_types.h (2)
  • void (1357-1362)
  • void (1364-1369)
Zend/zend_compile.h (3)
  • type (933-933)
  • type (1011-1011)
  • name (991-991)
Zend/zend_execute.h (4)
  • name (37-37)
  • name (51-51)
  • name (52-52)
  • name (421-421)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: WINDOWS_X64_ZTS
  • GitHub Check: MACOS_ARM64_DEBUG_NTS
  • GitHub Check: LINUX_X64_DEBUG_ZTS_ASAN
  • GitHub Check: FREEBSD
  • GitHub Check: LINUX_X64_RELEASE_NTS
  • GitHub Check: LINUX_X32_DEBUG_ZTS
  • GitHub Check: BENCHMARKING
🔇 Additional comments (7)
Zend/zend_API.c (6)

2904-2913: Watch out for data races on global hashtable during cleanup.

zend_type_free_interned_trees() modifies the global interned_type_tree without synchronization. In multi-threaded contexts, this could lead to race conditions when the hash table is being freed.


3007-3048: LGTM - Good implementation of equality checks for type nodes

The type node equality check is well-structured with appropriate short-circuit logic. First checking if pointers are the same (a == b), then comparing kinds and type details, and recursively comparing compound types. This allows for efficient equality comparisons.


3050-3071: Watch out for data races on global hashtable insertion.

intern_type_node() modifies interned_type_tree without locks. If code runs in multi-threaded contexts, ensure thread safety or clarify usage constraints.


3073-3124: Sort and deduplicate type subtrees correctly

The implementation of zend_type_to_interned_tree efficiently handles both simple types and compound types (unions and intersections). It properly flattens compound types of the same kind and deduplicates children after sorting, which is a good practice for normalization.


3126-3151: LGTM - Good refactoring of zend_normalize_internal_type

The function has been well-refactored to return a type tree node pointer instead of void, leveraging the new type tree infrastructure. The change maintains compatibility with existing code while enhancing the type representation.


4894-4898: LGTM - Property type information is now stored in a structured format

Good implementation of storing type information using the type tree infrastructure. The code properly handles both persistent and non-persistent classes.

Zend/zend_types.h (1)

145-164: Well-designed type tree structure for complex type representation.

The introduction of the zend_type_node structure and zend_type_node_kind enum provides a robust framework for representing complex types in PHP's type system, including union and intersection types. The recursive structure allows for nested type relationships.

Some considerations for implementation:

  • Ensure proper memory management for the types pointer in compound types
  • Add validation when accessing union members based on the kind field
  • Consider adding more documentation about usage patterns

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
Zend/zend_API.c (2)

2913-2942: ⚠️ Potential issue

Fix string comparison logic in compare_simple_types

The current implementation has an issue in the string comparison logic. The function zend_string_equals_ci() returns a boolean value (1 for equal, 0 for not equal), but it's being used as if it returns a comparison result (-1, 0, 1).

Apply this fix to correct the comparison behavior:

if (a_has_name && b_has_name) {
    const zend_string *a_name = ZEND_TYPE_NAME(a);
    const zend_string *b_name = ZEND_TYPE_NAME(b);
-   const int cmp = zend_string_equals_ci(a_name, b_name);
-   if (cmp != 0) {
-       return cmp;
-   }
+   if (!zend_string_equals_ci(a_name, b_name)) {
+       // Names are not equal, return based on lexicographical order
+       return strcmp(ZSTR_VAL(a_name), ZSTR_VAL(b_name)) < 0 ? -1 : 1;
+   }
}

3048-3069: ⚠️ Potential issue

Watch out for data races on global hashtable insertion.

intern_type_node() modifies interned_type_tree without locks. If code runs in multi-threaded contexts, ensure thread safety or clarify usage constraints.

🧹 Nitpick comments (1)
Zend/zend_globals.h (1)

195-195: Type trees storage added to executor globals

The addition of the type trees field to executor globals enables runtime access to the type information collected during compilation. Note that there's a small formatting inconsistency with the semicolon placement compared to other declarations (it's placed at the end of the comment rather than after the member name).

Consider adjusting the formatting to match other declarations in this struct:

-	HashTable *type_trees		/* type trees table */;
+	HashTable *type_trees;		/* type trees table */
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c18a585 and f032844.

📒 Files selected for processing (4)
  • Zend/zend_API.c (4 hunks)
  • Zend/zend_execute_API.c (1 hunks)
  • Zend/zend_globals.h (2 hunks)
  • ext/opcache/ZendAccelerator.c (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • ext/opcache/ZendAccelerator.c
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: WINDOWS_X64_ZTS
  • GitHub Check: MACOS_ARM64_DEBUG_NTS
  • GitHub Check: LINUX_X64_DEBUG_ZTS_ASAN
  • GitHub Check: LINUX_X64_RELEASE_NTS
  • GitHub Check: LINUX_X32_DEBUG_ZTS
  • GitHub Check: BENCHMARKING
  • GitHub Check: FREEBSD
🔇 Additional comments (10)
Zend/zend_execute_API.c (1)

151-151: Type trees are now copied from compiler to executor

This addition ensures that the executor has access to the type trees defined during the compilation phase, following the same pattern used for function and class tables. This is a crucial step for enabling the enhanced type checking system.

Zend/zend_globals.h (1)

97-97: Type trees storage added to compiler globals

This new member provides storage for interned type trees in the compiler globals, enabling the new type handling functionality. The field is properly documented with a descriptive comment.

Zend/zend_API.c (8)

2901-2911: Properly freeing interned type trees implementation looks good.

The new function correctly implements cleanup to prevent memory leaks by iterating through the hash table and freeing complex structures.


2944-2968: Type node comparison logic looks correct.

The implementation provides a stable sorting order by first comparing kinds, then the number of types for compound types, and then recursively comparing each type.


2970-3003: Hash function implementation is well designed.

The FNV-1a hash algorithm implementation properly accounts for all node properties including recursive hashing for compound types.


3005-3046: Type node equality check is thorough and comprehensive.

Good implementation that checks deep equality of type nodes by recursively comparing all properties.


3071-3122: Comprehensive type tree conversion with proper normalization.

The implementation handles all edge cases well:

  • Empty types return NULL
  • Simple types are directly converted
  • Compound types are normalized with flattening, sorting, and deduplication

This ensures consistent and efficient type tree representations.


3124-3149: Good extension of normalize_internal_type to use the tree structure.

The function maintains its original functionality while adding support for the new type tree system, preserving backward compatibility.


3418-3418: Proper integration of type trees in function registration.

Argument info is now properly normalized and associated with type trees.


4893-4896: Correctly handles different class types for property type trees.

The code correctly differentiates between internal and user-defined classes when creating type trees for properties, using the appropriate normalization method for each case.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
Zend/zend_execute.c (1)

1115-1118: Remove or finalize commented-out code.

These commented-out lines referencing cache_slot appear to be a leftover or a placeholder. They may cause confusion or lead to unmaintained code. Consider either implementing the logic if needed or removing the commented code to maintain clarity.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c18395 and 283ec3e.

📒 Files selected for processing (1)
  • Zend/zend_execute.c (8 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
Zend/zend_execute.c (1)
Zend/zend_execute.h (1)
  • zend_check_user_type_slow (107-108)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: WINDOWS_X64_ZTS
  • GitHub Check: MACOS_ARM64_DEBUG_NTS
  • GitHub Check: LINUX_X64_DEBUG_ZTS_ASAN
  • GitHub Check: LINUX_X64_RELEASE_NTS
  • GitHub Check: FREEBSD
  • GitHub Check: BENCHMARKING
  • GitHub Check: LINUX_X32_DEBUG_ZTS
🔇 Additional comments (11)
Zend/zend_execute.c (11)

1145-1146: Function signature update looks valid.

Including zend_type_node *type_tree is a sensible approach to handle union/intersection types. No immediate concerns observed; just ensure all call sites are updated accordingly.


1149-1150: Check for null and simple types is well-structured.

This early check avoids unnecessary work for simple type scenarios. Good defensive approach.


1151-1154: Union type logic appears correct.

Returning true on the first successful subtype match is consistent with union semantics.


1156-1157: Returning false when no subtype matches is consistent.

This satisfies typical union short-circuit logic.


1159-1165: Intersection type block is well-implemented.

All types must succeed hence returning false once any fails is correct for an intersection.


1168-1170: Use of default case is correct.

Returning false for unknown type kinds is appropriate to avoid unintended behavior.


1174-1175: Additional check for object types ensures correctness.

Fetching the class entry only if the argument is an object is a good guard against incorrect type assumptions.


1176-1182: Object CE checking is valid; consider confirming cache safety.

Good use of instanceof_function to verify the object satisfies the type. Verify that PROGRESS_CACHE_SLOT() can't exceed array bounds if HAVE_CACHE_SLOT is false or if slot usage is out of range.


1184-1184: Type mask extraction looks fine.

The new line for extracting the full type mask is straightforward and has no apparent flaws.


1227-1227: Falling back to the slow path is consistent.

Delegating to zend_check_type_slow() for the final type check is a structured approach.


1231-1234: Extended slow-check usage aligns with the updated signature.

Using zend_check_type_slow() with extra parameters for user-type validation is coherent and follows the newly introduced pattern.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
Zend/zend_API.c (2)

2901-2912: ⚠️ Potential issue

Thread safety concerns with interned type trees.

The zend_type_free_interned_trees function handles cleanup of the global interned type trees, but there's no synchronization mechanism to protect the global CG(type_trees) from concurrent access during its creation, modification, or destruction.

Consider adding appropriate synchronization (mutex/lock) to protect this global data structure in ZTS mode, especially in the intern_type_node function where additions to the hash table happen.


2925-2933: ⚠️ Potential issue

Fix string comparison logic for correct ordering.

The current comparison code compares memory addresses of strings instead of their content, which is incorrect for non-interned strings with identical content but different memory locations.

Replace the pointer arithmetic with proper string comparison:

- const int cmp = ZSTR_VAL(a_name) - ZSTR_VAL(b_name);
- if (cmp != 0) {
-     return cmp;
- }
+ if (!zend_string_equals_ci(a_name, b_name)) {
+     // Names are not equal, return based on lexicographical order
+     return strcmp(ZSTR_VAL(a_name), ZSTR_VAL(b_name)) < 0 ? -1 : 1;
+ }
🧹 Nitpick comments (3)
Zend/zend_API.c (3)

3049-3070: Enhance hash table initialization and check for duplicates.

The intern_type_node function initializes the hash table but doesn't fully check for collisions from different node structures with the same hash.

Consider improving the function to handle hash collisions more explicitly by checking for true equality even when hash values match but the nodes are different. This would help prevent potential issues where different structures accidentally share the same hash value.

Also, consider increasing the initial size from 64 if profiling shows that more type nodes are typically interned.


3072-3124: Optimize memory allocation for empty or simple type trees.

The zend_type_to_interned_tree function allocates memory for children even when it's not needed (for empty types).

Consider optimizing memory usage with early returns for simple cases:

+ if (type.type_mask == 0) {
+     return NULL;
+ }
+
+ if (!ZEND_TYPE_HAS_LIST(type)) {
+     zend_type_node *node = pemalloc(sizeof(zend_type_node), 1);
+     node->kind = ZEND_TYPE_SIMPLE;
+     node->simple_type = type;
+     return intern_type_node(node);
+ }

This modification already appears in your code, but make sure it's working as intended by adding tests for edge cases.


3107-3115: Add documentation for sorting and deduplication logic.

The code sorts and deduplicates type nodes, but the logic and reasoning behind this approach aren't documented.

Add comments explaining why sorting and deduplication are necessary for the type tree structure, particularly for future maintainers who might not understand the rationale behind this approach.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 283ec3e and d9e510f.

📒 Files selected for processing (1)
  • Zend/zend_API.c (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: WINDOWS_X64_ZTS
  • GitHub Check: MACOS_ARM64_DEBUG_NTS
  • GitHub Check: LINUX_X64_DEBUG_ZTS_ASAN
  • GitHub Check: BENCHMARKING
  • GitHub Check: LINUX_X64_RELEASE_NTS
  • GitHub Check: LINUX_X32_DEBUG_ZTS
  • GitHub Check: FREEBSD
🔇 Additional comments (1)
Zend/zend_API.c (1)

4895-4898:

❓ Verification inconclusive

Ensure consistent error handling for property type trees.

The modified code assigns interned type trees to property info structures but doesn't include explicit error handling if the tree creation fails.

Verify that the zend_type_to_interned_tree function handles all error cases properly and won't return NULL for valid inputs. Run the following script to check for NULL checks when using property type trees:


🏁 Script executed:

#!/bin/bash
# Search for NULL checks after zend_type_to_interned_tree calls
rg "type_tree = zend_type_to_interned_tree\(.*\)" -A 3 | grep -A 2 "if.*type_tree.*NULL\|type_tree == NULL"

# Also search for uses of property->type_tree with NULL checks
rg "->type_tree" -A 2 -B 2 | grep -A 2 -B 2 "if.*type_tree.*NULL\|type_tree == NULL"

Length of output: 601


Manual verification required: Consistent Error Handling for Property Type Trees

The automated search using the provided script encountered errors (related to argument parsing) and did not yield conclusive evidence that explicit NULL checks exist after calls to zend_type_to_interned_tree in Zend/zend_API.c. Please re-run the verification with corrected commands or perform a manual review to confirm whether:

  • The function zend_type_to_interned_tree internally guarantees a non-NULL result for valid inputs, or
  • Additional explicit NULL checks (e.g., immediately after the assignment to property_info->type_tree) should be introduced to ensure robust error handling.

For example, you might try a revised search:

#!/bin/bash
# Check for zend_type_to_interned_tree usage in Zend/zend_API.c with nearby NULL checks
rg -F "property_info->type_tree = zend_type_to_interned_tree(" Zend/zend_API.c -A 5 | grep -F "if (property_info->type_tree == NULL)"

If the internal guarantees of zend_type_to_interned_tree are insufficient, an explicit error handling branch should be added to handle failure cases.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
Zend/zend_API.c (1)

2932-2936: ⚠️ Potential issue

Fix pointer-based string comparison to ensure correct ordering.

The current string comparison uses pointer subtraction (ZSTR_VAL(a_name) - ZSTR_VAL(b_name)), which only checks if the string pointers are equal, not the actual string content. This will cause comparison to fail when two strings have identical content but different memory addresses.

Apply this diff to properly compare strings:

-const int cmp = ZSTR_VAL(a_name) - ZSTR_VAL(b_name);
-if (cmp != 0) {
-    return cmp;
-}
+if (!zend_string_equals_ci(a_name, b_name)) {
+    return strcmp(ZSTR_VAL(a_name), ZSTR_VAL(b_name)) < 0 ? -1 : 1;
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4f6e6c3 and 365cb0d.

📒 Files selected for processing (1)
  • Zend/zend_API.c (4 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
Zend/zend_API.c (1)
Zend/zend_API.h (2)
  • zend_type_free_interned_trees (452-452)
  • type (451-451)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: BENCHMARKING
  • GitHub Check: MACOS_ARM64_DEBUG_NTS
  • GitHub Check: LINUX_X32_DEBUG_ZTS
  • GitHub Check: FREEBSD
  • GitHub Check: LINUX_X64_DEBUG_ZTS_ASAN
  • GitHub Check: WINDOWS_X64_ZTS
  • GitHub Check: LINUX_X64_RELEASE_NTS
🔇 Additional comments (3)
Zend/zend_API.c (3)

3118-3121: Sort and deduplicate children nodes in a deterministic way.

This sorting and deduplication process is a good optimization for the type interning system. Ensuring unique, sorted type representations will improve comparison performance and reduce memory usage by eliminating redundant storage of identical type structures.


3162-3163: Update function return value for compatibility with type trees.

The modification of zend_normalize_internal_type() to return a zend_type_node* instead of void correctly implements the integration of the type tree system with the existing type normalization process.


4907-4910: Correctly handle type trees for both persistent and non-persistent classes.

The implementation properly distinguishes between persistent and non-persistent classes when initializing type trees, which ensures appropriate memory management based on the class's lifetime.

withinboredom pushed a commit that referenced this pull request Mar 29, 2025
```
ext/gd/libgd/gd.c:2275:14: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
    #0 0x5d6a2103e1db in php_gd_gdImageCopy /home/dcarlier/Contribs/php-src/ext/gd/libgd/gd.c:2275
    #1 0x5d6a210a2b63 in gdImageCrop /home/dcarlier/Contribs/php-src/ext/gd/libgd/gd_crop.c:57
    #2 0x5d6a21018ca4 in zif_imagecrop /home/dcarlier/Contribs/php-src/ext/gd/gd.c:3575
    #3 0x5d6a21e46e7a in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:1337
    #4 0x5d6a221188da in execute_ex /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:57246
    #5 0x5d6a221366bd in zend_execute /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:61634
    #6 0x5d6a21d107a6 in zend_execute_scripts /home/dcarlier/Contribs/php-src/Zend/zend.c:1895
    #7 0x5d6a21a63409 in php_execute_script /home/dcarlier/Contribs/php-src/main/main.c:2529
    #8 0x5d6a22516d5e in do_cli /home/dcarlier/Contribs/php-src/sapi/cli/php_cli.c:966
    php#9 0x5d6a2251981d in main /home/dcarlier/Contribs/php-src/sapi/cli/php_cli.c:1341
    php#10 0x7f10d002a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    php#11 0x7f10d002a47a in __libc_start_main_impl ../csu/libc-start.c:360
    php#12 0x5d6a20a06da4 in _start (/home/dcarlier/Contribs/php-src/sapi/cli/php+0x2806da4) (BuildId: d9a79c7e0e4872311439d7313cb3a81fe04190a2)
```

close phpGH-18006
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
Zend/zend_types.h (1)

145-164: Well-designed approach to representing type trees.

The addition of the zend_type_node structure and zend_type_node_kind enumeration provides a solid foundation for representing complex type hierarchies including simple types, unions, and intersections. The recursive design allows for nested type expressions.

A few considerations for future maintenance:

  • Ensure proper memory management for the dynamic array in compound types
  • Guard against potential stack overflow with deeply nested type trees
  • Consider adding more extensive documentation about usage patterns
Zend/zend_API.c (1)

2920-2949: The type comparison ordering could be more clearly documented.

The compare_simple_types function implements an ordering for type comparison, but the decision to use mask comparisons first, then string names, then nullability isn't explained. Consider adding comments about why this specific ordering was chosen for stable sorting.

 static int compare_simple_types(const zend_type a, const zend_type b) {
+    /* Compare types in this specific order:
+     * 1. Type mask values (for stable numeric ordering)
+     * 2. Class/type names (if present)
+     * 3. Nullability flags
+     */
     const uint32_t a_mask = ZEND_TYPE_FULL_MASK(a);
     const uint32_t b_mask = ZEND_TYPE_FULL_MASK(b);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 365cb0d and d1ca6c2.

📒 Files selected for processing (15)
  • Zend/zend.c (1 hunks)
  • Zend/zend_API.c (4 hunks)
  • Zend/zend_API.h (6 hunks)
  • Zend/zend_compile.c (3 hunks)
  • Zend/zend_compile.h (3 hunks)
  • Zend/zend_execute.c (8 hunks)
  • Zend/zend_execute.h (1 hunks)
  • Zend/zend_execute_API.c (1 hunks)
  • Zend/zend_globals.h (2 hunks)
  • Zend/zend_types.h (1 hunks)
  • Zend/zend_vm_def.h (1 hunks)
  • Zend/zend_vm_execute.h (5 hunks)
  • ext/opcache/ZendAccelerator.c (1 hunks)
  • ext/opcache/jit/zend_jit_helpers.c (2 hunks)
  • ext/zend_test/test.c (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • Zend/zend_globals.h
  • Zend/zend_vm_execute.h
  • Zend/zend_execute_API.c
  • Zend/zend.c
  • Zend/zend_compile.h
  • ext/opcache/ZendAccelerator.c
  • ext/zend_test/test.c
  • Zend/zend_execute.c
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: WINDOWS_X64_ZTS
  • GitHub Check: MACOS_ARM64_DEBUG_NTS
  • GitHub Check: LINUX_X64_DEBUG_ZTS_ASAN
  • GitHub Check: LINUX_X64_RELEASE_NTS
  • GitHub Check: FREEBSD
  • GitHub Check: LINUX_X32_DEBUG_ZTS
  • GitHub Check: BENCHMARKING
🔇 Additional comments (21)
Zend/zend_vm_def.h (1)

4430-4430:

❓ Verification inconclusive

Confirm ret_info->type_tree is allocated before use.

Please double-check that ret_info->type_tree is always initialized prior to invoking zend_check_type_slow(). If it can be NULL or uninitialized in any scenario, this could result in undefined behavior or segmentation faults.

To verify, you may run a search for all ret_info->type_tree references within the repository to ensure it is properly constructed and assigned before being passed here:


🏁 Script executed:

#!/bin/bash
# Description: Search for all references to ret_info->type_tree
rg -A 5 "ret_info->type_tree"

Length of output: 2535


Action Required: Verify Allocation of ret_info->type_tree

The search confirms that ret_info->type_tree is consistently passed to type-checking functions (both the fast and slow variants) in several files (e.g., Zend/zend_execute.c, Zend/zend_vm_def.h, and Zend/zend_vm_execute.h). However, we did not locate any explicit assignments or initializations for ret_info->type_tree in the search results. Please ensure that all code paths initializing the ret_info structure correctly allocate and assign type_tree prior to these type-checking calls. This includes verifying that any construction or initialization function for ret_info properly sets up type_tree even in edge cases.

Zend/zend_compile.c (3)

7350-7351: Minor formatting improvement noted.

The added newline after the assignment to ast->attr improves readability by separating this operation from the return statement.


7585-7589: Type tree initialization added.

This change adds initialization of the type_tree field using the newly introduced zend_type_to_interned_tree function to convert the existing type information into the new interned tree structure. This is part of the core implementation needed for the type trees feature.


7834-7836: Type tree initialization for argument information.

Similar to the previous change, this adds initialization of the type_tree field for argument information objects. The empty line before this initialization improves readability by separating it from the attribute-related code above.

Zend/zend_execute.h (1)

107-108:

✅ Verification successful

Function signature updated with new type_tree parameter

The function signature for zend_check_user_type_slow has been updated to include a new parameter zend_type_node *type_tree between the existing zend_type *type and zval *arg parameters. This change is aligned with the PR objective of integrating interned type trees into the Zend Engine's type handling process.


🏁 Script executed:

#!/bin/bash
# Check for all callers of zend_check_user_type_slow to verify they've been updated with the new parameter
rg -A 2 "zend_check_user_type_slow\s*\(" --type c

Length of output: 1086


Review Verified: Function signature change for zend_check_user_type_slow confirmed

The updated function signature in Zend/zend_execute.h now correctly includes the new zend_type_node *type_tree parameter between zend_type *type and zval *arg. Verification of all caller sites (e.g., in ext/opcache/jit/zend_jit_helpers.c and Zend/zend_execute.c) confirms that they have been updated accordingly.

ext/opcache/jit/zend_jit_helpers.c (2)

1899-1911: Signature updated to pass type_tree to type checking function

The function has been updated to include a new parameter to zend_check_user_type_slow, passing arg_info->type_tree as the second argument. This change is part of the broader integration of interned type trees for type handling in the Zend Engine.


1913-1925: Similar type_tree parameter added to return type checking

The function has been updated to include the arg_info->type_tree parameter when calling zend_check_user_type_slow. This ensures consistent type checking behavior for both argument and return type verification, maintaining the PR's objective of integrating type trees for type handling.

Zend/zend_API.h (3)

131-165: Consistent pattern of adding type_tree parameter to argument information macros.

All the argument information macros have been updated to include a NULL parameter for the type_tree field, which aligns with the overall goal of integrating interned type trees into the Zend Engine's type handling system.


170-216: Return type information macros updated with type_tree field.

These return type information macros have been modified to include the NULL parameter for the type_tree field, maintaining consistency with the argument information macros.


451-452: New API functions for type tree handling.

Two new functions have been added to support the type tree functionality:

  1. zend_type_to_interned_tree - Converts a zend_type to an interned tree structure
  2. zend_type_free_interned_trees - Deallocates interned type nodes

These functions will enable proper management of the new type tree structures throughout the Zend Engine.

Zend/zend_API.c (11)

2901-2918: Well-implemented memory management function for type trees.

This new function properly cleans up memory allocated for type tree structures, handling both simple and compound types correctly. It ensures proper string reference counting for interned strings and correctly frees memory based on allocation type.


2977-3010: Good implementation of FNV-1a hash function for type nodes.

The hashing function is well-implemented using the FNV-1a algorithm, which is a good choice for hashing structures like this. The function properly handles different node kinds and recursively computes hashes for compound types.


3012-3053: Thorough equality check implementation for type nodes.

The equality function correctly handles the recursive nature of type nodes and properly compares both simple and compound types. Good optimization with the early return when pointers are identical.


3086-3138: Good implementation of type tree interning with deduplication.

The zend_type_to_interned_tree function handles both simple and compound types, with smart flattening of nested compounds of the same kind and deduplication of identical child nodes. The sorting for deterministic output is a nice touch.


3121-3122: Excellent use of sorting for deterministic tree representation.

Sorting the nodes ensures that equivalent type representations result in the same interned tree, regardless of the order in which types were originally declared. This is critical for proper deduplication and type comparison.


3123-3129: Efficient deduplication of children nodes.

The deduplication logic is efficient and correctly handles the case where sorting might have placed identical nodes next to each other. This is important for memory optimization when dealing with complex type trees.


3140-3164: Good integration with existing type normalization.

The function correctly handles the interning of class names and normalizes the types before creating the interned tree, leveraging the existing zend_new_interned_string and zend_alloc_ce_cache functions for class names.


3434-3434: Critical integration in property type handling.

This line updates property_info->type_tree to use the newly interned type tree system, which is a key point of integration with the existing property system. This change ensures that property types are properly normalized and interned.


4909-4912: Good type handling in property declaration.

The implementation correctly differentiates between internal (persistent) and user-defined classes when creating type trees for properties, using the appropriate normalization functions in each case.


3055-3084:

❓ Verification inconclusive

Consider thread safety in intern_type_node function.

The function uses a global hash table CG(type_trees) without explicit locking mechanisms. In ZTS (Zend Thread Safety) mode, this might lead to race conditions if multiple threads try to intern type nodes simultaneously.


🏁 Script executed:

#!/bin/bash
# Check if there are any mutex or locking mechanisms related to type_trees in the codebase
rg "type_trees.*lock|mutex.*type_trees" --type c

Length of output: 50


Thread safety in intern_type_node: Verify Locking Mechanisms

The global hash table CG(type_trees) is accessed without any explicit locking here. A simple grep for locking patterns related to type_trees didn't yield any results, which raises the possibility that in a ZTS (Zend Thread Safety) build, concurrent calls to intern_type_node might lead to race conditions. Please manually verify that:

  • Either this function (or the caller context) applies a higher-level lock protecting CG(type_trees) in a multithreaded environment.
  • Or an appropriate locking mechanism is introduced to safeguard the hash table’s initialization and modifications.

File: Zend/zend_API.c, Lines: 3055–3084


3110-3119:

❓ Verification inconclusive

Potential issue with recursive type handling.

When processing child nodes in a compound type, any node of the same kind (union/intersection) gets flattened and its children are directly incorporated. However, there's no protection against cyclic type definitions, which could lead to infinite recursion.

Could PHP type declarations create cyclic references that might cause issues here? For example, through type aliases or generics in future PHP versions?


🌐 Web query:

Can PHP type declarations create cyclic references?

💡 Result:

PHP's type declarations themselves do not inherently create cyclic references, but certain coding patterns involving circular dependencies between classes can lead to cyclic references if not managed properly. Here's a breakdown of the key considerations:

1. Circular Dependencies vs Cyclic References

  • Circular dependencies occur when classes reference each other through inheritance or composition (e.g., Class A uses Class B, which in turn uses Class A). PHP handles these through autoloaders[2], but requires careful implementation:
    // Autoloader allows loading interdependent classes
    spl_autoload_register(function($class) {
        if ($class === 'A') class A extends B {}
        if ($class === 'B') class B extends C {}
        if ($class === 'C') class C extends A {}
    });
  • Cyclic references typically refer to object instances retaining mutual references (e.g., $objA->link = $objB; $objB->link = $objA;), which can prevent garbage collection[3].

2. Type Declaration Mechanics
PHP's type system allows class/interface references in:

  • Method parameters (function foo(ClassA $param))
  • Return types (function bar(): ClassB)
  • Properties (private ClassC $prop)

While these can create circular dependencies in class definitions, they don't directly cause cyclic references in object instances. PHP 7.4+ handles class loading dependencies through early class registration during inheritance checks[2].

3. Memory Considerations
True cyclic references between object instances can cause memory leaks unless:

$foo = new Foo('Foo1');
$bar = new Foo('Foo2');
$foo->setLink($bar);
$bar->setLink($foo);
// Explicit garbage collection needed
gc_collect_cycles(); // Forces cleanup [3]

4. Variance Checks
PHP 7.4+ improved handling of circular type dependencies through:

  • Three-stage class linking (unlinked → nearly linked → linked)
  • Allowing temporary "Schrödinger's class" states during autoloading[2]

Key Takeaways

  • Type declarations can participate in circular dependencies between classes, but PHP manages these through autoloader-aware inheritance resolution[2][6]
  • Actual cyclic references between object instances require manual garbage collection attention[3]
  • Traits with circular references may cause infinite recursion during static analysis[6]

For most applications, PHP's garbage collector and autoloader architecture adequately handle circular patterns, but developers should remain vigilant about object lifecycle management in long-running processes[1][3].

Citations:


Attention: Review of Recursive Type Flattening in zend_API.c

The current implementation of type flattening in the compound type handling does not include explicit safeguards against cyclic type definitions. Our web query confirms that PHP’s type declarations by themselves don’t inherently create cyclic references. However, while PHP internally manages circular dependencies gracefully with current mechanisms, there is a theoretical risk if future language features (e.g., generics or enhanced type aliases) allow self-referential or cyclic type definitions.

  • The code assumes a tree-like structure without cycles when flattening nodes of the same kind.
  • Though PHP's current type system avoids such cycles, consider whether additional checks should be introduced to prevent potential infinite recursion if cyclic definitions ever occur.

Please verify that cycles are not possible (or are well-handled) in the context where this flattening logic is used.

Comment on lines +2932 to +2938
const zend_string *a_name = ZEND_TYPE_NAME(a);
const zend_string *b_name = ZEND_TYPE_NAME(b);
const int cmp = ZSTR_VAL(a_name) - ZSTR_VAL(b_name);
if (cmp != 0) {
return cmp;
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential bug in type name comparison logic.

The current implementation compares string pointers (ZSTR_VAL(a_name) - ZSTR_VAL(b_name)) rather than string contents. This works if the strings are interned but could fail otherwise. A safer approach would be to use zend_string_equals_ci() as is done in zend_type_node_equals().

-        const int cmp = ZSTR_VAL(a_name) - ZSTR_VAL(b_name);
-        if (cmp != 0) {
-            return cmp;
-        }
+        /* Use case-insensitive comparison for type names, 
+         * as PHP type declarations are case-insensitive */
+        int result = zend_binary_strcasecmp(
+            ZSTR_VAL(a_name), ZSTR_LEN(a_name),
+            ZSTR_VAL(b_name), ZSTR_LEN(b_name));
+        if (result != 0) {
+            return result;
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const zend_string *a_name = ZEND_TYPE_NAME(a);
const zend_string *b_name = ZEND_TYPE_NAME(b);
const int cmp = ZSTR_VAL(a_name) - ZSTR_VAL(b_name);
if (cmp != 0) {
return cmp;
}
}
const zend_string *a_name = ZEND_TYPE_NAME(a);
const zend_string *b_name = ZEND_TYPE_NAME(b);
/* Use case-insensitive comparison for type names,
* as PHP type declarations are case-insensitive */
int result = zend_binary_strcasecmp(
ZSTR_VAL(a_name), ZSTR_LEN(a_name),
ZSTR_VAL(b_name), ZSTR_LEN(b_name));
if (result != 0) {
return result;
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant