← All results

Conflicting property types composed from two traits

Group: Cross-analyzer regressions · Category: regression · File: regressions_trait_property_type_conflict.php

LeftTrait::$prop is string and RightTrait::$prop is int. Composing both into one class is a compile-time fatal error in PHP ("traits define the same property … the definition differs and is considered incompatible"). Analyzers diverge on whether they report this statically. PHPStan is silent even though the program cannot run. Source lead: Mago analyzer test trait_property_type_conflicts.

Analyzer results

AnalyzerVersionResultDiagnostics
phan 6.0.7Phan 6.0.7 php-ast version 1.1.3 PHP version used to run Phan: 8.5.9 Pass
regressions_trait_property_type_conflict.php:20: Declaration of \Conformance\Tests\RegressionsTraitPropertyTypeConflict\Composed::prop of real type string is incompatible with inherited property \Conformance\Tests\RegressionsTraitPropertyTypeConflict\RightTrait::prop of real type int defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/regressions_trait_property_type_conflict.php:25 [PhanIncompatibleRealPropertyType]
phpstan 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 Pass

No diagnostics reported.

psalm 6.16.1Psalm 6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac
next: 7.0.0-beta19
Pass (pzoom≠)
regressions_trait_property_type_conflict.php:20: Conformance\Tests\RegressionsTraitPropertyTypeConflict\Composed has an uninitialized property Conformance\Tests\RegressionsTraitPropertyTypeConflict\LeftTrait::$prop, but no constructor [MissingConstructor]
pzoom (Psalm port)
regressions_trait_property_type_conflict.php:28: Conformance\Tests\RegressionsTraitPropertyTypeConflict\Composed has an uninitialized property Conformance\Tests\RegressionsTraitPropertyTypeConflict\Composed::$prop, but no constructor [MissingConstructor]
mago 1.46.0mago 1.46.0 Pass
regressions_trait_property_type_conflict.php:31: Property `$prop` is defined differently in `Conformance\Tests\RegressionsTraitPropertyTypeConflict\LeftTrait` and `Conformance\Tests\RegressionsTraitPropertyTypeConflict\RightTrait` used by `conformance\tests\regressionstraitpropertytypeconflict\composed`: type declaration differs (TUnion { types: [Scalar(String(TString { literal: None, is_numeric: false, is_truthy: false, is_non_empty: false, is_callable: false, casing: Unspecified }))], flags: UnionFlags(0) } vs TUnion { types: [Scalar(Integer(Unspecified))], flags: UnionFlags(0) }) [incompatible-property-type]
mir 0.70.1mir 0.70.1 Pass

No diagnostics reported.

phpantom 0.9.0phpantom_lsp 0.9.0 Pass

No diagnostics reported.

intelephense 1.18.5intelephense 1.18.5 Pass

No diagnostics reported.

phpy 0.2.0phpy 0.2.0 Pass

No diagnostics reported.

qodana 262.8665.325Qodana 262.8665.325 Pass

No diagnostics reported.

noverify 0.5.5NoVerify, version 0.5.5: built on: 2025.04.22 14:36:46 OS: r-kuchinskas arm64 Commit: 4774b82f8adc53fbef38f95e97af4b953b4d1529 Pass

No diagnostics reported.

steins 0.1.5steins 0.1.5 (2026-08-12 revision 39b4cc1) Pass

No diagnostics reported.

phpstan-strict 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 Pass

No diagnostics reported.

psalm-next 7.0.0-beta19Psalm 7.0.0-beta19@7e751c06a756fa64dc4c759c09fe4a173afcb433 Pass
regressions_trait_property_type_conflict.php:20: Conformance\Tests\RegressionsTraitPropertyTypeConflict\Composed has an uninitialized property Conformance\Tests\RegressionsTraitPropertyTypeConflict\LeftTrait::$prop, but no constructor [MissingConstructor]

Source

<?php

declare(strict_types=1);

namespace Conformance\Tests\RegressionsTraitPropertyTypeConflict;

/**
 * Conflicting property types composed from two traits.
 *
 * `LeftTrait::$prop` is `string` and `RightTrait::$prop` is `int`. Composing both into one
 * class is a compile-time fatal error in PHP ("traits define the same property … the
 * definition differs and is considered incompatible"). Analyzers diverge on whether they
 * report this statically. PHPStan is silent even though the program cannot run.
 *
 * Source lead: Mago analyzer test `trait_property_type_conflicts`.
 */

trait LeftTrait
{
    public string $prop; // E<psalm>: reports only MissingConstructor for the uninitialized $prop, not the type conflict // E<phan>: PhanIncompatibleRealPropertyType — detects the string-vs-int conflict
}

trait RightTrait
{
    public int $prop;
}

final class Composed
{
    use LeftTrait;
    use RightTrait; // E<mago>: incompatible-property-type — detects the conflict. PHPStan is silent on both the conflict and the missing constructor, even though PHP fatals at compile time
}