# How TypePHP Handles Native Types with `use native_types`

> Discover how TypePHP handles native types using use native_types. Learn how it eliminates zval boxing by mapping PHP scalars to C++ ABI types for efficient compilation.

- Repository: [Swoole Project/typephp](https://github.com/swoole/typephp)
- Tags: internals
- Published: 2026-08-30

---

**TypePHP toggles a global native-type compilation mode via the `use native_types` directive, which eliminates `zval` boxing by mapping PHP scalars directly to C++ ABI types throughout the compiler pipeline.**

TypePHP is a transpiler that compiles PHP to native C++ for the Swoole ecosystem. When developers declare `use native_types` in a script, the parser sets an internal `$this->nativeTypes` flag that propagates through every subsequent compiler phase, enabling zero-cost abstractions for scalar operations.

## How the `use native_types` Directive Activates the Compiler

The native type system begins in the declaration parsing phase. When the tokenizer encounters the `use native_types` statement, the resolver immediately flips a boolean flag that persists for the remainder of the compilation unit.

### Detection in DeclarationSymbolTrait.php

In [`src/Resolver/DeclarationSymbolTrait.php`](https://github.com/swoole/typephp/blob/main/src/Resolver/DeclarationSymbolTrait.php), the parser analyzes `use` declarations to detect the native types directive. Upon recognition, it assigns `$this->nativeTypes = true`, signaling to all downstream transforms that scalar types should be treated as native C++ primitives rather than PHP `zval` containers.

This flag check appears in the compiler base and throughout the transformation pipeline, allowing conditional emission of native ABI code versus generic Zend VM compatible code.

## Native Type Detection and Mapping

Once the flag is set, the compiler must distinguish between native scalars and standard PHP types. This classification determines whether a variable requires heap allocation or can reside in CPU registers.

### TypeDetectionTrait.php Implementation

The [`src/Parser/TypeDetectionTrait.php`](https://github.com/swoole/typephp/blob/main/src/Parser/TypeDetectionTrait.php) file provides the core classification logic through two key methods:

- `isNativeType()` – Returns true for scalars like `int`, `float`, `bool`, and `bigint`
- `getNativeType()` – Maps PHP type names to their corresponding C++ ABI equivalents (e.g., `int` → `int`, `float` → `double`)

These helpers are invoked during AST construction to annotate type nodes with native classification metadata, enabling later optimizer passes to skip `zval` boxing logic.

## Code Generation Optimizations

With native type detection enabled, multiple compiler components bypass generic PHP runtime overhead and emit direct native arithmetic and memory operations.

### Arithmetic and Assignment Operations

In [`src/Transform/BinaryOpTrait.php`](https://github.com/swoole/typephp/blob/main/src/Transform/BinaryOpTrait.php) and [`src/Transform/AssignOpTrait.php`](https://github.com/swoole/typephp/blob/main/src/Transform/AssignOpTrait.php), the compiler checks `$this->nativeTypes` before emitting code. When the flag is true and both operands are classified as native scalars, the transform emits direct C++ arithmetic (e.g., `a + b`) instead of `zval` addition helpers. This eliminates function call overhead and enables LLVM/SIMD optimizations during the final C++ compilation phase.

### Function Calls and Parameter Validation

The [`src/Transform/ParameterValidationLowering.php`](https://github.com/swoole/typephp/blob/main/src/Transform/ParameterValidationLowering.php) component generates argument conversion routines that pass scalars directly to functions without boxing. For strict scalar typing, it inserts `genStrictScalarArgConversion` checks that validate types at the boundary before passing raw `int`, `double`, or `bool` values into the function body.

Similarly, [`src/Optimizer/FuncCallOptimizer.php`](https://github.com/swoole/typephp/blob/main/src/Optimizer/FuncCallOptimizer.php) leverages the native type flag to skip `zval` allocation for return values, allowing functions to return primitives directly to callers.

## Native Classes and Object Handling

The native type system extends beyond scalars to support entire classes that exist outside the Zend VM heap, enabling high-performance data structures that interoperate with C++ libraries.

### NativeClassAttributeLowering.php

When processing class declarations, [`src/Transform/NativeClassAttributeLowering.php`](https://github.com/swoole/typephp/blob/main/src/Transform/NativeClassAttributeLowering.php) marks qualifying classes with `$classDef->nativeObject = true`. Native classes can contain only native-typed properties and methods, ensuring that instances occupy contiguous memory without `zval` indirection. The lowering pass generates C++ struct definitions and accessor methods that map directly to the underlying native layout.

### NativeTypeCompatibilityTrait.php

The [`src/TypeSystem/NativeTypeCompatibilityTrait.php`](https://github.com/swoole/typephp/blob/main/src/TypeSystem/NativeTypeCompatibilityTrait.php) enforces safety invariants across the type system. It provides `getReturnType()` resolution for native signatures and `isNativeObjectClass()` checks that prevent illegal cross-boundary inheritance—specifically, ensuring that native objects never extend or implement non-native PHP interfaces, which would violate ABI compatibility.

## Practical Compilation Example

Consider a script that leverages the native type system for mathematical operations:

```php
<?php
use native_types;

function calculate(int $x, float $y): float {
    return $x * $y + 2.5;
}

native class Point {
    public native int $x;
    public native int $y;
    
    public native function distance(Point $other): float;
}
?>

```

When `use native_types` is active, TypePHP generates C++ code that bypasses the Zend VM entirely:

```cpp
double calculate(int x, double y) {
    return (x * y) + 2.5;  // Direct register arithmetic, no zval allocation
}

struct Point {
    int x;
    int y;
    
    double distance(const Point& other) {
        // Native C++ implementation accessing members directly
        return std::hypot(x - other.x, y - other.y);
    }
};

```

Without the directive, the same PHP code would compile to `zval`-centric implementations using `ZVAL_LONG`, `ZVAL_DOUBLE`, and `zend_function` call overhead, incurring significant memory indirection and CPU cache pressure.

## Summary

- **Directive Activation**: The `use native_types` statement in [`src/Resolver/DeclarationSymbolTrait.php`](https://github.com/swoole/typephp/blob/main/src/Resolver/DeclarationSymbolTrait.php) sets `$this->nativeTypes` to true, triggering native ABI generation.
- **Type Classification**: [`src/Parser/TypeDetectionTrait.php`](https://github.com/swoole/typephp/blob/main/src/Parser/TypeDetectionTrait.php) provides `isNativeType()` and `getNativeType()` to map PHP scalars to C++ primitives.
- **Zero-Cost Operations**: Binary and assignment operations in [`BinaryOpTrait.php`](https://github.com/swoole/typephp/blob/main/BinaryOpTrait.php) emit direct C++ arithmetic when native types are enabled.
- **Boundary Optimization**: [`ParameterValidationLowering.php`](https://github.com/swoole/typephp/blob/main/ParameterValidationLowering.php) passes unboxed scalars to functions and validates strict typing only at entry points.
- **Native Objects**: [`NativeClassAttributeLowering.php`](https://github.com/swoole/typephp/blob/main/NativeClassAttributeLowering.php) generates C++ structs with `$classDef->nativeObject` marking, while [`NativeTypeCompatibilityTrait.php`](https://github.com/swoole/typephp/blob/main/NativeTypeCompatibilityTrait.php) enforces ABI safety constraints.

## Frequently Asked Questions

### What PHP types qualify as native types in TypePHP?

TypePHP recognizes `int`, `float`, `bool`, and `bigint` as native scalars when `use native_types` is declared. These map directly to C++ `int`, `double`, `bool`, and 64-bit integer types respectively, residing on the stack or in CPU registers rather than the Zend heap.

### Can native classes extend regular PHP classes?

No. According to [`src/TypeSystem/NativeTypeCompatibilityTrait.php`](https://github.com/swoole/typephp/blob/main/src/TypeSystem/NativeTypeCompatibilityTrait.php), native classes marked with `$classDef->nativeObject = true` cannot extend or implement non-native PHP types. This restriction prevents ABI violations where a native struct layout would be incompatible with `zval` expectations in the Zend VM.

### Does `use native_types` affect function argument validation?

Yes. The [`src/Transform/ParameterValidationLowering.php`](https://github.com/swoole/typephp/blob/main/src/Transform/ParameterValidationLowering.php) component consults the `$this->nativeTypes` flag to generate `genStrictScalarArgConversion` guards. When active, arguments are validated once at the function boundary and then passed as raw C++ primitives, eliminating repetitive type checks and `zval` extraction inside the function body.

### What happens if I omit `use native_types` in a script?

Without the directive, TypePHP defaults to standard PHP semantics where all values are represented as `zval` structures. The compiler ignores native type hints for ABI purposes, generating code that interacts with the Zend VM's heap and reference counting, which provides full PHP compatibility at the cost of performance.