larastan: Internal error with macros and named parameters

  • Larastan Version: 1.0.3 (the 2.x series is certainly affected too)
  • PHPStan Version: 1.7.2 to 1.7.11
  • --level used: 5

Description

After upgrading to PHPStan 1.7.2 I got this error:

 -- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
     Error                                                                                                                                                                                                                                                                                   
 -- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
     Internal error: Internal error: An optional parameter must have a default value in file /var/www/app/Services/[redacted].php                                                                                                                                
                                                                                                                                                                                                                                                                                             
     Post the following stack trace to https://github.com/phpstan/phpstan/issues/new?template=Bug_report.md:                                                                                                                                                                                 
     #0 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/ArgumentsNormalizer.php(32): PHPStan\Analyser\ArgumentsNormalizer::reorderArgs(Object(PHPStan\Reflection\ResolvedFunctionVariant), Object(PhpParser\Node\Expr\MethodCall))                                          
     #1 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(3432): PHPStan\Analyser\ArgumentsNormalizer::reorderMethodArguments(Object(PHPStan\Reflection\ResolvedFunctionVariant), Object(PhpParser\Node\Expr\MethodCall))                                   
     #2 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1365): PHPStan\Analyser\MutatingScope->methodCallReturnType(Object(PHPStan\Type\ObjectType), 'rememberLock', Object(PhpParser\Node\Expr\MethodCall))                                              
     #3 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1371): PHPStan\Analyser\MutatingScope->PHPStan\Analyser\{closure}()                                                                                                                               
     #4 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(551): PHPStan\Analyser\MutatingScope->resolveType(Object(PhpParser\Node\Expr\MethodCall))                                                                                                         
     #5 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Rules/FunctionReturnTypeCheck.php(54): PHPStan\Analyser\MutatingScope->getType(Object(PhpParser\Node\Expr\MethodCall))                                                                                                       
     #6 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Rules/Methods/ReturnTypeRule.php(43): PHPStan\Rules\FunctionReturnTypeCheck->checkReturnType(Object(PHPStan\Analyser\MutatingScope), Object(PHPStan\Type\ArrayType), Object(PhpParser\Node\Expr\MethodCall),                 
     Object(PhpParser\Node\Stmt\Return_), 'Method App\\Serv...', 'Method App\\Serv...', 'Method App\\Serv...', 'Method App\\Serv...', false)                                                                                                                                                
     #7 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(102): PHPStan\Rules\Methods\ReturnTypeRule->processNode(Object(PhpParser\Node\Stmt\Return_), Object(PHPStan\Analyser\MutatingScope))                                                               
     #8 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Node/ClassStatementsGatherer.php(95): PHPStan\Analyser\FileAnalyser->PHPStan\Analyser\{closure}(Object(PhpParser\Node\Stmt\Return_), Object(PHPStan\Analyser\MutatingScope))                                                 
     #9 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(460): PHPStan\Node\ClassStatementsGatherer->__invoke(Object(PhpParser\Node\Stmt\Return_), Object(PHPStan\Analyser\MutatingScope))                                                             
     #10 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(380): PHPStan\Analyser\NodeScopeResolver::PHPStan\Analyser\{closure}(Object(PhpParser\Node\Stmt\Return_), Object(PHPStan\Analyser\MutatingScope))                                            
     #11 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(325): PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\Return_), Object(PHPStan\Analyser\MutatingScope), Object(Closure))                                      
     #12 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(475): PHPStan\Analyser\NodeScopeResolver->processStmtNodes(Object(PhpParser\Node\Stmt\ClassMethod), Array, Object(PHPStan\Analyser\MutatingScope), Object(Closure))                          
     #13 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(325): PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\ClassMethod), Object(PHPStan\Analyser\MutatingScope), Object(PHPStan\Node\ClassStatementsGatherer))     
     #14 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(553): PHPStan\Analyser\NodeScopeResolver->processStmtNodes(Object(PhpParser\Node\Stmt\Class_), Array, Object(PHPStan\Analyser\MutatingScope), Object(PHPStan\Node\ClassStatementsGatherer))  
     #15 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(325): PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\Class_), Object(PHPStan\Analyser\MutatingScope), Object(Closure))                                       
     #16 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(525): PHPStan\Analyser\NodeScopeResolver->processStmtNodes(Object(PhpParser\Node\Stmt\Namespace_), Array, Object(PHPStan\Analyser\MutatingScope), Object(Closure))                           
     #17 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(296): PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\Namespace_), Object(PHPStan\Analyser\MutatingScope), Object(Closure))                                   
     #18 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(189): PHPStan\Analyser\NodeScopeResolver->processNodes(Array, Object(PHPStan\Analyser\MutatingScope), Object(Closure))                                                                            
     #19 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(143): PHPStan\Analyser\FileAnalyser->analyseFile('/var/www/app/Se...', Array, Object(PHPStan\Rules\Registry), NULL)                                                                              
     #20 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97): PHPStan\Command\WorkerCommand->PHPStan\Command\{closure}(Array)                                                                                             
     #21 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/clue/ndjson-react/src/Decoder.php(110): _PHPStan_23e95a9f5\Evenement\EventEmitter->emit('data', Array)                                                                                                                   
     #22 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97): _PHPStan_23e95a9f5\Clue\React\NDJson\Decoder->handleData(Array)                                                                                             
     #23 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/Util.php(62): _PHPStan_23e95a9f5\Evenement\EventEmitter->emit('data', Array)                                                                                                                           
     #24 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97): _PHPStan_23e95a9f5\React\Stream\Util::_PHPStan_23e95a9f5\React\Stream\{closure}('{"action":"anal...')                                                       
     #25 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/DuplexResourceStream.php(154): _PHPStan_23e95a9f5\Evenement\EventEmitter->emit('data', Array)                                                                                                           
     #26 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(201): _PHPStan_23e95a9f5\React\Stream\DuplexResourceStream->handleData(Resource id #6942)                                                                                      
     #27 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(173): _PHPStan_23e95a9f5\React\EventLoop\StreamSelectLoop->waitForStreamActivity(NULL)                                                                                         
     #28 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(106): _PHPStan_23e95a9f5\React\EventLoop\StreamSelectLoop->run()                                                                                                                                 
     #29 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Command/Command.php(259): PHPStan\Command\WorkerCommand->execute(Object(_PHPStan_23e95a9f5\Symfony\Component\Console\Input\ArgvInput),                                                                   
     Object(_PHPStan_23e95a9f5\Symfony\Component\Console\Output\ConsoleOutput))                                                                                                                                                                                                              
     #30 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(856): _PHPStan_23e95a9f5\Symfony\Component\Console\Command\Command->run(Object(_PHPStan_23e95a9f5\Symfony\Component\Console\Input\ArgvInput),                                            
     Object(_PHPStan_23e95a9f5\Symfony\Component\Console\Output\ConsoleOutput))                                                                                                                                                                                                              
     #31 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(259): _PHPStan_23e95a9f5\Symfony\Component\Console\Application->doRunCommand(Object(PHPStan\Command\WorkerCommand),                                                                      
     Object(_PHPStan_23e95a9f5\Symfony\Component\Console\Input\ArgvInput), Object(_PHPStan_23e95a9f5\Symfony\Component\Console\Output\ConsoleOutput))                                                                                                                                        
     #32 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(157): _PHPStan_23e95a9f5\Symfony\Component\Console\Application->doRun(Object(_PHPStan_23e95a9f5\Symfony\Component\Console\Input\ArgvInput),                                              
     Object(_PHPStan_23e95a9f5\Symfony\Component\Console\Output\ConsoleOutput))                                                                                                                                                                                                              
     #33 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(127): _PHPStan_23e95a9f5\Symfony\Component\Console\Application->run()                                                                                                                                              
     #34 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(128): _PHPStan_23e95a9f5\{closure}()                                                                                                                                                                                
     #35 /var/www/vendor/phpstan/phpstan/phpstan(8): require('phar:///var/www...')                                                                                                                                                                                                           
     #36 /var/www/vendor/bin/phpstan(117): include('/var/www/vendor...')                                                                                                                                                                                                                     
     #37 {main}                                                                                                                                                                                                                                                                              
     Child process error (exit code 1):                                                                                                                                                                                                                                                      
 -- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 


                                                                                                                        
 [ERROR] Found 2 errors                                                                                                 
                                                                                                                        

Used memory: 192.36 MB

After debugging a little I found out the object in $methodReflection is an instance of NunoMaduro\Larastan\Methods\Macro. Furthermore the default value of parameters returned by Macro is always null. I think this causes an issue with the recent versions of PHPStan.

Please let me know if you need more details.

Laravel code where the issue was found

The code of the project has been redacted.

    public function foo(bool $fresh = false): array
    {
        return \Cache::tags(self::CACHE_TAGS)->rememberLock('foobar', 3600, callback: function () {
            // snip
            return [];
        }, refresh: $fresh);
    }

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 15 (8 by maintainers)

Most upvoted comments

Great to hear. We are waiting for a new PHPStan release in order to make a new release here with the fix.

I don‘t get the error anymore.

FYI: I started working on this. But looks like it’s gonna take some time.

Can anyone affected by this give fix-macros branch a try? Thanks.

This is a misunderstanding. That comment was definitely not sarcasm.

I sincerely apologize then.

IMHO the problem comes from here: https://github.com/nunomaduro/larastan/blob/5805225/src/Methods/Macro.php#L197-L199

getDefaultValue() shouldn’t always return null.

By replacing null by new MixedType() the error goes away for instance. EDIT I’m not saying it’s the solution, just it could help finding the root cause of the issue

I have created a repository to reproduce the issue: https://github.com/villfa/reproducer_larastan_1267

Run

git clone https://github.com/villfa/reproducer_larastan_1267.git
cd reproducer_larastan_1267
composer install
./vendor/bin/phpstan analyse

and you’ll get

 -- -------------------------------------------------------------------------------------------------------------------------------------------------------- 
     Error                                                                                                                                                   
 -- -------------------------------------------------------------------------------------------------------------------------------------------------------- 
     Internal error: Internal error: An optional parameter must have a default value in file /reproducer_larastan_1267/app/Providers/AppServiceProvider.php  
     Run PHPStan with -v option and post the stack trace to:                                                                                                 
     https://github.com/phpstan/phpstan/issues/new?template=Bug_report.md                                                                                    
     Child process error (exit code 1):                                                                                                                      
 -- -------------------------------------------------------------------------------------------------------------------------------------------------------- 

Hi,

How is the rememberLock method defined? That is not a default Laravel method I guess.