Skip to content

Conversation

@ivanvasechko
Copy link

Problem

The extractor was not detecting changes to class-level attributes when updating stubs between PHP versions. It only compared methods and constants within classes, but never checked if the class declaration's own attributes (like #[Attribute(...)]) had changed.

This caused several attribute classes to have outdated stubs in PHP 8.5:

  • Override: Missing the addition of Attribute::TARGET_PROPERTY
  • Deprecated: Missing expansion to TARGET_CONSTANT|TARGET_CLASS and readonly properties
  • ReturnTypeWillChange: Missing the #[Attribute(Attribute::TARGET_METHOD)] declaration
  • Attribute: Missing self-attribute #[Attribute(Attribute::TARGET_CLASS)] and $flags property

Root Cause

In compareStatementsInNamespace() (~line 506), after comparing class members (methods and constants), the code would simply return the old class statement without comparing the class's attrGroups:

$old->stmts = $newStmtsToSet;
return [$old];

Solution

  1. Added new method hasAttributeChanges() that compares class-level attributes between old and new class declarations

    • Filters out #[Since] and #[Until] meta-attributes
    • Compares attribute names, argument counts, and argument values using prettyPrintExpr()
    • Returns true if any difference is detected
  2. Modified compareStatementsInNamespace() to check for class-level attribute changes before returning

    • If changes detected, calls stmtDiff() to generate both #[Until] and #[Since] versions

Testing

Ran the extractor with PHP 8.5 source (./extractor/extract.php --update -- 8.4 8.5) and verified:

  • ✅ Override class now correctly has two versions (TARGET_METHOD vs TARGET_METHOD|TARGET_PROPERTY)
  • ✅ Deprecated class properly versioned with expanded targets and readonly properties
  • ✅ ReturnTypeWillChange class properly versioned with new attribute
  • ✅ Attribute class properly versioned with self-attribute and flags property

Impact

This fix ensures PHPStan can correctly:

  • Allow #[\Override] on properties in PHP 8.5+
  • Recognize expanded attribute targets for #[\Deprecated]
  • Properly type-check all attribute-related changes in PHP 8.5

References

@ivanvasechko ivanvasechko marked this pull request as ready for review November 25, 2025 10:27
@ivanvasechko
Copy link
Author

@ondrejmirtes
Copy link
Member

PHPStan itself is not reading these attributes, it uses phpstorm-stubs for that.

In this repo I'm generally interested only in fixing bugs that manifesr in PHPStan. Are you using this repo for some other purpose?

@ivanvasechko
Copy link
Author

ivanvasechko commented Nov 25, 2025

PHPStan itself is not reading these attributes, it uses phpstorm-stubs for that.

In this repo I'm generally interested only in fixing bugs that manifesr in PHPStan. Are you using this repo for some other purpose?

Not really, just facing the error with PHP 8.5 and the latest PHP Stan.

php -v

PHP 8.5.0 (cli) (built: Nov 20 2025 19:48:32) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.5.0, Copyright (c) Zend Technologies
    with Zend OPcache v8.5.0, Copyright (c), by Zend Technologies
composer show phpstan/phpstan
name     : phpstan/phpstan
descrip. : PHPStan - PHP Static Analysis Tool
keywords : dev, static analysis
versions : * 2.1.32
released : 2025-11-11, last week
type     : library
license  : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage : 
source   : []  
dist     : [zip] https://api.github.com/repos/phpstan/phpstan/zipball/e126cad1e30a99b137b8ed75a85a676450ebb227 e126cad1e30a99b137b8ed75a85a676450ebb227
path     : /var/www/html/vendor/phpstan/phpstan
names    : phpstan/phpstan

Trying to set checkMissingOverridePropertyAttribute: true, and getting such an error:

Note: Using configuration file /var/www/html/phpstan.neon.
 4/4 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ --------------------------------------------------------------------------------------------------------------------- 
  Line   Models/User.php                                                                                                      
 ------ --------------------------------------------------------------------------------------------------------------------- 
  22     Property App\Models\User::$fillable overrides property Illuminate\Database\Eloquent\Model::$fillable but is missing  
         the #[\Override] attribute.                                                                                          
         🪪  property.missingOverride                                                                                         
  33     Property App\Models\User::$hidden overrides property Illuminate\Database\Eloquent\Model::$hidden but is missing the  
         #[\Override] attribute.                                                                                              
         🪪  property.missingOverride                                                                                         
 ------ --------------------------------------------------------------------------------------------------------------------- 


                                                                                                                        
 [ERROR] Found 2 errors                                                                                                 

If adding #[\Override] attribute like this:

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    #[\Override]
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    #[\Override]
    protected $hidden = [
        'password',
        'remember_token',
    ];

Getting a new error:

root@31ab76a196d5:/var/www/html# vendor/bin/phpstan
Note: Using configuration file /var/www/html/phpstan.neon.
 4/4 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ ------------------------------------------------------------- 
  Line   Models/User.php                                              
 ------ ------------------------------------------------------------- 
  22     Attribute class Override does not have the property target.  
         🪪  attribute.target                                         
  34     Attribute class Override does not have the property target.  
         🪪  attribute.target                                         
 ------ ------------------------------------------------------------- 


                                                                                                                        
 [ERROR] Found 2 errors                                                                                                                                                                                                                      

So my assumption was that there is something wrong with stubs.


If it's not what used by PHPStan, feel free to close the PR, sorry for the confusion.

@ondrejmirtes
Copy link
Member

Please open an issue in phpstan/phpstan.

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.

2 participants