briannesbitt / Carbon

A simple PHP API extension for DateTime.
https://carbon.nesbot.com/
MIT License
16.58k stars 1.28k forks source link

Using "Depends on the following methods" @method in traits causes PHPStan to lose knowledge of type resulting in errors #3046

Closed philbates35 closed 5 months ago

philbates35 commented 5 months ago

Hello,

I encountered an issue with the following code:

function doSomethingWithACarbon(\Carbon\Carbon $date): void {
    //
}
function doSomethingWithACarbonImmutable(\Carbon\CarbonImmutable $date): void {
    //
}

doSomethingWithACarbon(\Carbon\Carbon::today()->next(\Carbon\Carbon::WEDNESDAY));
doSomethingWithACarbonImmutable(\Carbon\CarbonImmutable::today()->next(\Carbon\CarbonImmutable::WEDNESDAY));

Carbon version: 3.6.0

PHP version: 8.2

When running PHPStan (1.11.5) on level 5, I expected to get:

 [OK] No errors          

But I actually get:

 ------ ------------------------------------------------------------------------------------------------------------------------------ 
  Line   web-playground.php                                                                                                            
 ------ ------------------------------------------------------------------------------------------------------------------------------ 
  10     Parameter #1 $date of function doSomethingWithACarbon expects Carbon\Carbon, Carbon\CarbonInterface given.                    
  11     Parameter #1 $date of function doSomethingWithACarbonImmutable expects Carbon\CarbonImmutable, Carbon\CarbonInterface given.  
 ------ ------------------------------------------------------------------------------------------------------------------------------ 

But if I make the following change to src/Carbon/Traits/Week.php:

  * Depends on the following methods:
  *
  * @method CarbonInterface addWeeks(int $weeks = 1)
  * @method CarbonInterface copy()
  * @method CarbonInterface dayOfYear(int $dayOfYear)
  * @method string getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
- * @method CarbonInterface next(int|string $modifier = null)
  * @method CarbonInterface startOfWeek(int $day = null)
  * @method CarbonInterface subWeeks(int $weeks = 1)
  * @method CarbonInterface year(int $year = null)
  */
  trait Week
  {

Then I get:

 [OK] No errors          

Alternatively, if I make the following change to src/Carbon/Traits/Week.php:

  * Depends on the following methods:
  *
  * @method CarbonInterface addWeeks(int $weeks = 1)
  * @method CarbonInterface copy()
  * @method CarbonInterface dayOfYear(int $dayOfYear)
  * @method string getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
- * @method CarbonInterface next(int|string $modifier = null)
+ * @method static next(int|string $modifier = null)
  * @method CarbonInterface startOfWeek(int $day = null)
  * @method CarbonInterface subWeeks(int $weeks = 1)
  * @method CarbonInterface year(int $year = null)
  */
  trait Week
  {

Then I also get:

 [OK] No errors          

You can see that even though Carbon::next and CarbonInterface::next both have return type hint as static, the @method CarbonInterface next(int|string $modifier = null) in Week trait (used by both Carbon and CarbonImmutable) is taking priority causing these false positives.

I'm not sure whether the correct fix is to drop the use of the @method docblocks, or change the return type hint from CarbonInterface to static, or something else.

Let me know if you have any more questions or need more info, happy to help where I can!