{"record":{"id":"4e970cbe3147b2d4","repo":"sebastianbergmann/phpunit","slug":"parameter-of-comparison-method-s-s-does-not-h","errorCode":null,"errorMessage":"Parameter of comparison method %s::%s() does not have a declared type.","messagePattern":"Parameter of comparison method (.+?)::(.+?)\\(\\) does not have a declared type\\.","errorType":"exception","errorClass":"ComparisonMethodDoesNotDeclareParameterTypeException","httpStatus":null,"severity":"error","filePath":"src/Framework/Constraint/Object/ObjectEquals.php","lineNumber":124,"sourceCode":"        if ($returnType->getName() !== 'bool') {\n            throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(\n                $other::class,\n                $this->method,\n            );\n        }\n\n        if ($method->getNumberOfParameters() !== 1 || $method->getNumberOfRequiredParameters() !== 1) {\n            throw new ComparisonMethodDoesNotDeclareExactlyOneParameterException(\n                $other::class,\n                $this->method,\n            );\n        }\n\n        assert(count($method->getParameters()) > 0);\n        $parameter = $method->getParameters()[0];\n\n        if (!$parameter->hasType()) {\n            throw new ComparisonMethodDoesNotDeclareParameterTypeException(\n                $other::class,\n                $this->method,\n            );\n        }\n\n        $type = $parameter->getType();\n\n        if (!$type instanceof ReflectionNamedType) {\n            throw new ComparisonMethodDoesNotDeclareParameterTypeException(\n                $other::class,\n                $this->method,\n            );\n        }\n\n        $typeName = $type->getName();\n\n        if ($typeName === 'self') {\n            // @codeCoverageIgnoreStart","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Framework/Constraint/Object/ObjectEquals.php#L106-L142","documentation":"The single parameter of the comparison method used by assertObjectEquals() must have a declared type, so PHPUnit can verify the expected object is acceptable before invoking it. This variant is thrown when ReflectionParameter::hasType() is false, i.e. the parameter is untyped.","triggerScenarios":"equals() declared as `public function equals($other): bool` — the parameter has no type declaration, often because it was written to accept anything (Java `Object $other` style) or predates PHP 7 type hints.","commonSituations":"Legacy equals(mixed $other) implementations (here 'mixed' as an explicit declared type would be fine, absence of any hint is not); code style guides that banned parameter types; docblock-typed but not natively typed parameters.","solutions":["Add a parameter type, ideally `self` or the concrete class: `public function equals(self $other): bool`","If the method genuinely accepts any object, declare it explicitly: `public function equals(mixed $other): bool` — 'mixed' is a declared type and passes this check","Note: with a wide type you may then hit the instanceof acceptance check; prefer self or the specific value class"],"exampleFix":"// before\nclass Sku\n{\n    public function equals($other): bool\n    {\n        return $other instanceof self && $this->code === $other->code;\n    }\n}\n\n// after\nclass Sku\n{\n    public function equals(self $other): bool\n    {\n        return $this->code === $other->code;\n    }\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function comparisonMethodParameterIsTyped(object $actual, string $method = 'equals'): bool\n{\n    $params = (new ReflectionObject($actual))->getMethod($method)->getParameters();\n    return isset($params[0]) && $params[0]->hasType();\n}","tryCatchPattern":null,"preventionTips":["Always declare the parameter type, ideally `self` or the concrete value class","Explicit `mixed` counts as a type, but a self-typed parameter gives better safety and clearer failures"],"tags":["php","phpunit","assertobjectequals","parameter-type","equals-method"],"backgroundTag":"equals-method-contract-violation","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}