From 983b716347c7971ea1f9122cbe7109939371aea8 Mon Sep 17 00:00:00 2001
From: Benjamin Franzke <ben@bnf.dev>
Date: Tue, 23 Jan 2024 08:14:58 +0100
Subject: [PATCH] [TASK] Use first class closures for service provider
 factories
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Adapt the service provider compiler to perform the same level of
optimization as for the array-based callable syntax:
We unroll the static closure into its static components (class name and
method name). That means the effective generated dependency injection
php code is the same as before with the gain of better DX.

Note that first class closures can only be used where methods of the
current scope are referenced, late state binding is not supported.
AbstractServiceProvider therefore keeps using array-based callable
syntax to be able to reference method scope of extending classes.

Resolves: #103104
Releases: main, 12.4
Change-Id: I2f8ca7a69b1b69c51b1ff6bec384ddafe4492a41
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83033
Tested-by: Benjamin Franzke <ben@bnf.dev>
Reviewed-by: Benjamin Franzke <ben@bnf.dev>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: core-ci <typo3@b13.com>
---
 .../backend/Classes/ServiceProvider.php       |  28 ++---
 .../ServiceProviderCompilationPass.php        |  13 ++
 .../Package/AbstractServiceProvider.php       |   2 +-
 typo3/sysext/core/Classes/ServiceProvider.php | 118 +++++++++---------
 .../Fixtures/TestServiceProvider.php          |   8 ++
 .../ServiceProviderCompilationPassTest.php    |   4 +
 .../dashboard/Classes/ServiceProvider.php     |  20 +--
 .../extbase/Classes/ServiceProvider.php       |  10 +-
 .../sysext/fluid/Classes/ServiceProvider.php  |   6 +-
 .../frontend/Classes/ServiceProvider.php      |   7 +-
 .../install/Classes/ServiceProvider.php       |  64 +++++-----
 11 files changed, 153 insertions(+), 127 deletions(-)

diff --git a/typo3/sysext/backend/Classes/ServiceProvider.php b/typo3/sysext/backend/Classes/ServiceProvider.php
index f87c5320afc6..8eb0abda0b80 100644
--- a/typo3/sysext/backend/Classes/ServiceProvider.php
+++ b/typo3/sysext/backend/Classes/ServiceProvider.php
@@ -63,26 +63,26 @@ class ServiceProvider extends AbstractServiceProvider
     public function getFactories(): array
     {
         return [
-            Application::class => [ static::class, 'getApplication' ],
-            RequestHandler::class => [ static::class, 'getRequestHandler' ],
-            RouteDispatcher::class => [ static::class, 'getRouteDispatcher' ],
-            UriBuilder::class => [ static::class, 'getUriBuilder' ],
-            ModuleProvider::class => [ static::class, 'getModuleProvider' ],
-            ModuleFactory::class => [ static::class, 'getModuleFactory' ],
-            ModuleRegistry::class => [ static::class, 'getModuleRegistry' ],
-            'backend.middlewares' => [ static::class, 'getBackendMiddlewares' ],
-            'backend.routes' => [ static::class, 'getBackendRoutes' ],
-            'backend.routes.warmer' => [ static::class, 'getBackendRoutesWarmer' ],
-            'backend.modules' => [ static::class, 'getBackendModules' ],
-            'backend.modules.warmer' => [ static::class, 'getBackendModulesWarmer' ],
+            Application::class => self::getApplication(...),
+            RequestHandler::class => self::getRequestHandler(...),
+            RouteDispatcher::class => self::getRouteDispatcher(...),
+            UriBuilder::class => self::getUriBuilder(...),
+            ModuleProvider::class => self::getModuleProvider(...),
+            ModuleFactory::class => self::getModuleFactory(...),
+            ModuleRegistry::class => self::getModuleRegistry(...),
+            'backend.middlewares' => self::getBackendMiddlewares(...),
+            'backend.routes' => self::getBackendRoutes(...),
+            'backend.routes.warmer' => self::getBackendRoutesWarmer(...),
+            'backend.modules' => self::getBackendModules(...),
+            'backend.modules.warmer' => self::getBackendModulesWarmer(...),
         ];
     }
 
     public function getExtensions(): array
     {
         return [
-            Router::class => [ static::class, 'configureBackendRouter' ],
-            ListenerProvider::class => [ static::class, 'addEventListeners' ],
+            Router::class => self::configureBackendRouter(...),
+            ListenerProvider::class => self::addEventListeners(...),
         ] + parent::getExtensions();
     }
 
diff --git a/typo3/sysext/core/Classes/DependencyInjection/ServiceProviderCompilationPass.php b/typo3/sysext/core/Classes/DependencyInjection/ServiceProviderCompilationPass.php
index 0c40cbbc9309..3b53cfab41c7 100644
--- a/typo3/sysext/core/Classes/DependencyInjection/ServiceProviderCompilationPass.php
+++ b/typo3/sysext/core/Classes/DependencyInjection/ServiceProviderCompilationPass.php
@@ -197,6 +197,19 @@ class ServiceProviderCompilationPass implements CompilerPassInterface
             return $callable;
         }
 
+        if ($callable instanceof \Closure) {
+            $reflection = new \ReflectionFunction($callable);
+            $reflectionScope = $reflection->getClosureScopeClass();
+            $usedVariables = count($reflection->getClosureUsedVariables());
+
+            if ($reflection->isStatic() && !str_contains($reflection->getName(), '{closure}') && $reflectionScope !== null && $usedVariables === 0) {
+                return [
+                    $reflectionScope->getName(),
+                    $reflection->getName(),
+                ];
+            }
+        }
+
         return null;
     }
 
diff --git a/typo3/sysext/core/Classes/Package/AbstractServiceProvider.php b/typo3/sysext/core/Classes/Package/AbstractServiceProvider.php
index 0aa8e1b48e3b..053834388179 100644
--- a/typo3/sysext/core/Classes/Package/AbstractServiceProvider.php
+++ b/typo3/sysext/core/Classes/Package/AbstractServiceProvider.php
@@ -57,7 +57,7 @@ abstract class AbstractServiceProvider implements ServiceProviderInterface
             // @deprecated since v12, will be removed with v13 together with class PageTsConfigLoader.
             'globalPageTsConfig' => [ static::class, 'configureGlobalPageTsConfig' ],
             'backend.modules' => [ static::class, 'configureBackendModules' ],
-            'content.security.policies' => [static::class, 'configureContentSecurityPolicies'],
+            'content.security.policies' => [ static::class, 'configureContentSecurityPolicies' ],
             'icons' => [ static::class, 'configureIcons' ],
         ];
     }
diff --git a/typo3/sysext/core/Classes/ServiceProvider.php b/typo3/sysext/core/Classes/ServiceProvider.php
index 00b393457fa9..58760aef93e4 100644
--- a/typo3/sysext/core/Classes/ServiceProvider.php
+++ b/typo3/sysext/core/Classes/ServiceProvider.php
@@ -50,74 +50,74 @@ class ServiceProvider extends AbstractServiceProvider
     public function getFactories(): array
     {
         return [
-            SymfonyEventDispatcher::class => [ static::class, 'getSymfonyEventDispatcher' ],
-            Cache\CacheManager::class => [ static::class, 'getCacheManager' ],
-            Database\ConnectionPool::class => [ static::class, 'getConnectionPool' ],
-            Charset\CharsetConverter::class => [ static::class, 'getCharsetConverter' ],
-            Configuration\SiteConfiguration::class => [ static::class, 'getSiteConfiguration' ],
-            Command\ListCommand::class => [ static::class, 'getListCommand' ],
-            HelpCommand::class => [ static::class, 'getHelpCommand' ],
-            Command\CacheFlushCommand::class => [ static::class, 'getCacheFlushCommand' ],
-            Command\CacheWarmupCommand::class => [ static::class, 'getCacheWarmupCommand' ],
-            Command\DumpAutoloadCommand::class => [ static::class, 'getDumpAutoloadCommand' ],
-            Console\CommandApplication::class => [ static::class, 'getConsoleCommandApplication' ],
-            Console\CommandRegistry::class => [ static::class, 'getConsoleCommandRegistry' ],
-            Context\Context::class => [ static::class, 'getContext' ],
-            Core\BootService::class => [ static::class, 'getBootService' ],
-            Crypto\PasswordHashing\PasswordHashFactory::class => [ static::class, 'getPasswordHashFactory' ],
-            EventDispatcher\EventDispatcher::class => [ static::class, 'getEventDispatcher' ],
-            EventDispatcher\ListenerProvider::class => [ static::class, 'getEventListenerProvider' ],
-            FormProtection\FormProtectionFactory::class => [ static::class, 'getFormProtectionFactory' ],
-            Http\Client\GuzzleClientFactory::class => [ static::class, 'getGuzzleClientFactory' ],
-            Http\MiddlewareStackResolver::class => [ static::class, 'getMiddlewareStackResolver' ],
-            Http\RequestFactory::class => [ static::class, 'getRequestFactory' ],
-            Imaging\IconFactory::class => [ static::class, 'getIconFactory' ],
-            Imaging\IconRegistry::class => [ static::class, 'getIconRegistry' ],
-            Localization\LanguageServiceFactory::class => [ static::class, 'getLanguageServiceFactory' ],
-            Localization\LanguageStore::class => [ static::class, 'getLanguageStore' ],
-            Localization\Locales::class => [ static::class, 'getLocales' ],
-            Localization\LocalizationFactory::class => [ static::class, 'getLocalizationFactory' ],
-            Mail\TransportFactory::class => [ static::class, 'getMailTransportFactory' ],
-            Messaging\FlashMessageService::class => [ static::class, 'getFlashMessageService' ],
-            Middleware\ResponsePropagation::class => [ static::class, 'getResponsePropagationMiddleware' ],
-            Middleware\VerifyHostHeader::class => [ static::class, 'getVerifyHostHeaderMiddleware' ],
-            Package\FailsafePackageManager::class => [ static::class, 'getFailsafePackageManager' ],
-            Package\Cache\PackageDependentCacheIdentifier::class => [ static::class, 'getPackageDependentCacheIdentifier' ],
-            Routing\BackendEntryPointResolver::class => [ static::class, 'getBackendEntryPointResolver' ],
-            Routing\RequestContextFactory::class => [ static::class, 'getRequestContextFactory' ],
-            Registry::class => [ static::class, 'getRegistry' ],
-            Resource\Index\FileIndexRepository::class => [ static::class, 'getFileIndexRepository' ],
-            Resource\Index\MetaDataRepository::class => [ static::class, 'getMetaDataRepository' ],
-            Resource\Driver\DriverRegistry::class => [ static::class, 'getDriverRegistry' ],
-            Resource\ProcessedFileRepository::class => [ static::class, 'getProcessedFileRepository' ],
-            Resource\ResourceFactory::class => [ static::class, 'getResourceFactory' ],
-            Resource\StorageRepository::class => [ static::class, 'getStorageRepository' ],
-            Service\DependencyOrderingService::class => [ static::class, 'getDependencyOrderingService' ],
-            Service\FlexFormService::class => [ static::class, 'getFlexFormService' ],
-            Service\OpcodeCacheService::class => [ static::class, 'getOpcodeCacheService' ],
-            TimeTracker\TimeTracker::class => [ static::class, 'getTimeTracker' ],
-            TypoScript\TypoScriptStringFactory::class => [ static::class, 'getTypoScriptStringFactory' ],
-            TypoScript\TypoScriptService::class => [ static::class, 'getTypoScriptService' ],
-            TypoScript\AST\Traverser\AstTraverser::class => [ static::class, 'getAstTraverser' ],
-            TypoScript\AST\CommentAwareAstBuilder::class => [ static::class, 'getCommentAwareAstBuilder' ],
+            SymfonyEventDispatcher::class => self::getSymfonyEventDispatcher(...),
+            Cache\CacheManager::class => self::getCacheManager(...),
+            Database\ConnectionPool::class => self::getConnectionPool(...),
+            Charset\CharsetConverter::class => self::getCharsetConverter(...),
+            Configuration\SiteConfiguration::class => self::getSiteConfiguration(...),
+            Command\ListCommand::class => self::getListCommand(...),
+            HelpCommand::class => self::getHelpCommand(...),
+            Command\CacheFlushCommand::class => self::getCacheFlushCommand(...),
+            Command\CacheWarmupCommand::class => self::getCacheWarmupCommand(...),
+            Command\DumpAutoloadCommand::class => self::getDumpAutoloadCommand(...),
+            Console\CommandApplication::class => self::getConsoleCommandApplication(...),
+            Console\CommandRegistry::class => self::getConsoleCommandRegistry(...),
+            Context\Context::class => self::getContext(...),
+            Core\BootService::class => self::getBootService(...),
+            Crypto\PasswordHashing\PasswordHashFactory::class => self::getPasswordHashFactory(...),
+            EventDispatcher\EventDispatcher::class => self::getEventDispatcher(...),
+            EventDispatcher\ListenerProvider::class => self::getEventListenerProvider(...),
+            FormProtection\FormProtectionFactory::class => self::getFormProtectionFactory(...),
+            Http\Client\GuzzleClientFactory::class => self::getGuzzleClientFactory(...),
+            Http\MiddlewareStackResolver::class => self::getMiddlewareStackResolver(...),
+            Http\RequestFactory::class => self::getRequestFactory(...),
+            Imaging\IconFactory::class => self::getIconFactory(...),
+            Imaging\IconRegistry::class => self::getIconRegistry(...),
+            Localization\LanguageServiceFactory::class => self::getLanguageServiceFactory(...),
+            Localization\LanguageStore::class => self::getLanguageStore(...),
+            Localization\Locales::class => self::getLocales(...),
+            Localization\LocalizationFactory::class => self::getLocalizationFactory(...),
+            Mail\TransportFactory::class => self::getMailTransportFactory(...),
+            Messaging\FlashMessageService::class => self::getFlashMessageService(...),
+            Middleware\ResponsePropagation::class => self::getResponsePropagationMiddleware(...),
+            Middleware\VerifyHostHeader::class => self::getVerifyHostHeaderMiddleware(...),
+            Package\FailsafePackageManager::class => self::getFailsafePackageManager(...),
+            Package\Cache\PackageDependentCacheIdentifier::class => self::getPackageDependentCacheIdentifier(...),
+            Routing\BackendEntryPointResolver::class => self::getBackendEntryPointResolver(...),
+            Routing\RequestContextFactory::class => self::getRequestContextFactory(...),
+            Registry::class => self::getRegistry(...),
+            Resource\Index\FileIndexRepository::class => self::getFileIndexRepository(...),
+            Resource\Index\MetaDataRepository::class => self::getMetaDataRepository(...),
+            Resource\Driver\DriverRegistry::class => self::getDriverRegistry(...),
+            Resource\ProcessedFileRepository::class => self::getProcessedFileRepository(...),
+            Resource\ResourceFactory::class => self::getResourceFactory(...),
+            Resource\StorageRepository::class => self::getStorageRepository(...),
+            Service\DependencyOrderingService::class => self::getDependencyOrderingService(...),
+            Service\FlexFormService::class => self::getFlexFormService(...),
+            Service\OpcodeCacheService::class => self::getOpcodeCacheService(...),
+            TimeTracker\TimeTracker::class => self::getTimeTracker(...),
+            TypoScript\TypoScriptStringFactory::class => self::getTypoScriptStringFactory(...),
+            TypoScript\TypoScriptService::class => self::getTypoScriptService(...),
+            TypoScript\AST\Traverser\AstTraverser::class => self::getAstTraverser(...),
+            TypoScript\AST\CommentAwareAstBuilder::class => self::getCommentAwareAstBuilder(...),
             TypoScript\Tokenizer\LosslessTokenizer::class => [ static::class, 'getLosslessTokenizer'],
             // @deprecated since v12, will be removed with v13 together with class PageTsConfigLoader.
-            'globalPageTsConfig' => [ static::class, 'getGlobalPageTsConfig' ],
-            'icons' => [ static::class, 'getIcons' ],
-            'middlewares' => [ static::class, 'getMiddlewares' ],
-            'content.security.policies' => [ static::class, 'getContentSecurityPolicies' ],
+            'globalPageTsConfig' => self::getGlobalPageTsConfig(...),
+            'icons' => self::getIcons(...),
+            'middlewares' => self::getMiddlewares(...),
+            'content.security.policies' => self::getContentSecurityPolicies(...),
         ];
     }
 
     public function getExtensions(): array
     {
         return [
-            Console\CommandRegistry::class => [ static::class, 'configureCommands' ],
-            Imaging\IconRegistry::class => [ static::class, 'configureIconRegistry' ],
+            Console\CommandRegistry::class => self::configureCommands(...),
+            Imaging\IconRegistry::class => self::configureIconRegistry(...),
             // @deprecated since v12, will be removed with v13 together with class PageTsConfigLoader.
-            Configuration\Loader\PageTsConfigLoader::class => [ static::class, 'configurePageTsConfigLoader' ],
-            EventDispatcherInterface::class => [ static::class, 'provideFallbackEventDispatcher' ],
-            EventDispatcher\ListenerProvider::class => [ static::class, 'extendEventListenerProvider' ],
+            Configuration\Loader\PageTsConfigLoader::class => self::configurePageTsConfigLoader(...),
+            EventDispatcherInterface::class => self::provideFallbackEventDispatcher(...),
+            EventDispatcher\ListenerProvider::class => self::extendEventListenerProvider(...),
         ] + parent::getExtensions();
     }
 
diff --git a/typo3/sysext/core/Tests/Unit/DependencyInjection/Fixtures/TestServiceProvider.php b/typo3/sysext/core/Tests/Unit/DependencyInjection/Fixtures/TestServiceProvider.php
index 8e82a8ccdcce..2ff4e3b9d129 100644
--- a/typo3/sysext/core/Tests/Unit/DependencyInjection/Fixtures/TestServiceProvider.php
+++ b/typo3/sysext/core/Tests/Unit/DependencyInjection/Fixtures/TestServiceProvider.php
@@ -52,6 +52,7 @@ class TestServiceProvider implements ServiceProviderInterface
                     return new \stdClass();
                 }
             },
+            'serviceE' => TestServiceProvider::createServiceE(...),
             'function' => 'TYPO3\\CMS\\Core\\Tests\\Unit\\DependencyInjection\\Fixtures\\myFunctionFactory',
         ];
     }
@@ -63,6 +64,13 @@ class TestServiceProvider implements ServiceProviderInterface
         return $instance;
     }
 
+    public static function createServiceE(ContainerInterface $container): \stdClass
+    {
+        $instance = new \stdClass();
+        $instance->parameter = 'baz';
+        return $instance;
+    }
+
     public function getExtensions(): array
     {
         return [];
diff --git a/typo3/sysext/core/Tests/Unit/DependencyInjection/ServiceProviderCompilationPassTest.php b/typo3/sysext/core/Tests/Unit/DependencyInjection/ServiceProviderCompilationPassTest.php
index 8fb4a1b17f00..20200b1c599a 100644
--- a/typo3/sysext/core/Tests/Unit/DependencyInjection/ServiceProviderCompilationPassTest.php
+++ b/typo3/sysext/core/Tests/Unit/DependencyInjection/ServiceProviderCompilationPassTest.php
@@ -76,9 +76,11 @@ final class ServiceProviderCompilationPassTest extends UnitTestCase
 
         $serviceA = $container->get('serviceA');
         $serviceD = $container->get('serviceD');
+        $serviceE = $container->get('serviceE');
 
         self::assertInstanceOf(\stdClass::class, $serviceA);
         self::assertInstanceOf(\stdClass::class, $serviceD);
+        self::assertInstanceOf(\stdClass::class, $serviceE);
         self::assertIsObject($container->get('function'));
     }
 
@@ -95,11 +97,13 @@ final class ServiceProviderCompilationPassTest extends UnitTestCase
 
         $serviceA = $container->get('serviceA');
         $serviceC = $container->get('serviceC');
+        $serviceE = $container->get('serviceE');
 
         self::assertInstanceOf(\stdClass::class, $serviceA);
         self::assertEquals('foo', $serviceA->newProperty);
         self::assertEquals('bar', $serviceA->newProperty2);
         self::assertEquals('localhost', $serviceC->serviceB->parameter);
+        self::assertEquals('baz', $serviceE->parameter);
     }
 
     /**
diff --git a/typo3/sysext/dashboard/Classes/ServiceProvider.php b/typo3/sysext/dashboard/Classes/ServiceProvider.php
index 120e9450c718..dc9a571967ff 100644
--- a/typo3/sysext/dashboard/Classes/ServiceProvider.php
+++ b/typo3/sysext/dashboard/Classes/ServiceProvider.php
@@ -45,22 +45,22 @@ class ServiceProvider extends AbstractServiceProvider
     public function getFactories(): array
     {
         return [
-            'dashboard.presets' => [ static::class, 'getDashboardPresets' ],
-            'dashboard.widgetGroups' => [ static::class, 'getWidgetGroups' ],
-            'dashboard.widgets' => [ static::class, 'getWidgets' ],
-            'dashboard.configuration.warmer' => [ static::class, 'getConfigurationWarmer' ],
+            'dashboard.presets' => self::getDashboardPresets(...),
+            'dashboard.widgetGroups' => self::getWidgetGroups(...),
+            'dashboard.widgets' => self::getWidgets(...),
+            'dashboard.configuration.warmer' => self::getConfigurationWarmer(...),
         ];
     }
 
     public function getExtensions(): array
     {
         return [
-            DashboardPresetRegistry::class => [ static::class, 'configureDashboardPresetRegistry' ],
-            ListenerProvider::class => [ static::class, 'addEventListeners' ],
-            WidgetGroupRegistry::class => [ static::class, 'configureWidgetGroupRegistry' ],
-            'dashboard.presets' => [ static::class, 'configureDashboardPresets' ],
-            'dashboard.widgetGroups' => [ static::class, 'configureWidgetGroups' ],
-            'dashboard.widgets' => [ static::class, 'configureWidgets' ],
+            DashboardPresetRegistry::class => self::configureDashboardPresetRegistry(...),
+            ListenerProvider::class => self::addEventListeners(...),
+            WidgetGroupRegistry::class => self::configureWidgetGroupRegistry(...),
+            'dashboard.presets' => self::configureDashboardPresets(...),
+            'dashboard.widgetGroups' => self::configureWidgetGroups(...),
+            'dashboard.widgets' => self::configureWidgets(...),
         ] + parent::getExtensions();
     }
 
diff --git a/typo3/sysext/extbase/Classes/ServiceProvider.php b/typo3/sysext/extbase/Classes/ServiceProvider.php
index 7ddd4d9467bf..e101647b7c40 100644
--- a/typo3/sysext/extbase/Classes/ServiceProvider.php
+++ b/typo3/sysext/extbase/Classes/ServiceProvider.php
@@ -41,11 +41,11 @@ class ServiceProvider extends AbstractServiceProvider
     public function getFactories(): array
     {
         return [
-            Configuration\ConfigurationManager::class => [ static::class, 'getConfigurationManager' ],
-            Reflection\ReflectionService::class => [ static::class, 'getReflectionService' ],
-            Service\ExtensionService::class => [ static::class, 'getExtensionService' ],
-            Service\ImageService::class => [ static::class, 'getImageService' ],
-            Security\Cryptography\HashService::class => [ static::class, 'getHashService' ],
+            Configuration\ConfigurationManager::class => self::getConfigurationManager(...),
+            Reflection\ReflectionService::class => self::getReflectionService(...),
+            Service\ExtensionService::class => self::getExtensionService(...),
+            Service\ImageService::class => self::getImageService(...),
+            Security\Cryptography\HashService::class => self::getHashService(...),
         ];
     }
 
diff --git a/typo3/sysext/fluid/Classes/ServiceProvider.php b/typo3/sysext/fluid/Classes/ServiceProvider.php
index 4a7a03462050..c2506c3b0428 100644
--- a/typo3/sysext/fluid/Classes/ServiceProvider.php
+++ b/typo3/sysext/fluid/Classes/ServiceProvider.php
@@ -39,9 +39,9 @@ class ServiceProvider extends AbstractServiceProvider
     public function getFactories(): array
     {
         return [
-            Core\Rendering\RenderingContextFactory::class => [ static::class, 'getRenderingContextFactory' ],
-            Core\ViewHelper\ViewHelperResolverFactory::class => [ static::class, 'getViewHelperResolverFactory' ],
-            Core\ViewHelper\ViewHelperResolverFactoryInterface::class => [ static::class, 'getViewHelperResolverFactoryInterface' ],
+            Core\Rendering\RenderingContextFactory::class => self::getRenderingContextFactory(...),
+            Core\ViewHelper\ViewHelperResolverFactory::class => self::getViewHelperResolverFactory(...),
+            Core\ViewHelper\ViewHelperResolverFactoryInterface::class => self::getViewHelperResolverFactoryInterface(...),
         ];
     }
 
diff --git a/typo3/sysext/frontend/Classes/ServiceProvider.php b/typo3/sysext/frontend/Classes/ServiceProvider.php
index 00f4c4dd1444..f659936d3701 100644
--- a/typo3/sysext/frontend/Classes/ServiceProvider.php
+++ b/typo3/sysext/frontend/Classes/ServiceProvider.php
@@ -48,10 +48,11 @@ class ServiceProvider extends AbstractServiceProvider
     public function getFactories(): array
     {
         return [
-            Http\Application::class => [ static::class, 'getApplication' ],
-            Http\RequestHandler::class => [ static::class, 'getRequestHandler' ],
-            'frontend.middlewares' => [ static::class, 'getFrontendMiddlewares' ],
+            Http\Application::class => self::getApplication(...),
+            Http\RequestHandler::class => self::getRequestHandler(...),
+            'frontend.middlewares' => self::getFrontendMiddlewares(...),
         ];
+
     }
 
     public static function getApplication(ContainerInterface $container): Http\Application
diff --git a/typo3/sysext/install/Classes/ServiceProvider.php b/typo3/sysext/install/Classes/ServiceProvider.php
index 08f5817735bb..de52fd71d5d5 100644
--- a/typo3/sysext/install/Classes/ServiceProvider.php
+++ b/typo3/sysext/install/Classes/ServiceProvider.php
@@ -68,37 +68,37 @@ class ServiceProvider extends AbstractServiceProvider
     public function getFactories(): array
     {
         return [
-            Authentication\AuthenticationService::class => [ static::class, 'getAuthenticationService' ],
-            Http\Application::class => [ static::class, 'getApplication' ],
-            Http\NotFoundRequestHandler::class => [ static::class, 'getNotFoundRequestHandler' ],
-            Service\ClearCacheService::class => [ static::class, 'getClearCacheService' ],
-            Service\CoreUpdateService::class => [ static::class, 'getCoreUpdateService' ],
-            Service\CoreVersionService::class => [ static::class, 'getCoreVersionService' ],
-            Service\LanguagePackService::class => [ static::class, 'getLanguagePackService' ],
-            Service\LateBootService::class => [ static::class, 'getLateBootService' ],
-            Service\LoadTcaService::class => [ static::class, 'getLoadTcaService' ],
-            Service\SilentConfigurationUpgradeService::class => [ static::class, 'getSilentConfigurationUpgradeService' ],
-            Service\SilentTemplateFileUpgradeService::class => [ static::class, 'getSilentTemplateFileUpgradeService' ],
-            Service\WebServerConfigurationFileService::class => [ static::class, 'getWebServerConfigurationFileService' ],
-            Service\DatabaseUpgradeWizardsService::class => [ static::class, 'getDatabaseUpgradeWizardsService' ],
-            Service\SetupService::class => [ static::class, 'getSetupService' ],
-            Service\SetupDatabaseService::class => [ static::class, 'getSetupDatabaseService' ],
-            Middleware\Installer::class => [ static::class, 'getInstallerMiddleware' ],
-            Middleware\Maintenance::class => [ static::class, 'getMaintenanceMiddleware' ],
-            Controller\EnvironmentController::class => [ static::class, 'getEnvironmentController' ],
-            Controller\IconController::class => [ static::class, 'getIconController' ],
-            Controller\InstallerController::class => [ static::class, 'getInstallerController' ],
-            Controller\LayoutController::class => [ static::class, 'getLayoutController' ],
-            Controller\LoginController::class => [ static::class, 'getLoginController' ],
-            Controller\MaintenanceController::class => [ static::class, 'getMaintenanceController' ],
-            Controller\SettingsController::class => [ static::class, 'getSettingsController' ],
-            Controller\UpgradeController::class => [ static::class, 'getUpgradeController' ],
-            Command\LanguagePackCommand::class => [ static::class, 'getLanguagePackCommand' ],
-            Command\UpgradeWizardRunCommand::class => [ static::class, 'getUpgradeWizardRunCommand' ],
-            Command\UpgradeWizardListCommand::class => [ static::class, 'getUpgradeWizardListCommand' ],
-            Command\SetupCommand::class => [ static::class, 'getSetupCommand' ],
-            Database\PermissionsCheck::class => [ static::class, 'getPermissionsCheck' ],
-            Mailer::class => [ static::class, 'getMailer' ],
+            Authentication\AuthenticationService::class => self::getAuthenticationService(...),
+            Http\Application::class => self::getApplication(...),
+            Http\NotFoundRequestHandler::class => self::getNotFoundRequestHandler(...),
+            Service\ClearCacheService::class => self::getClearCacheService(...),
+            Service\CoreUpdateService::class => self::getCoreUpdateService(...),
+            Service\CoreVersionService::class => self::getCoreVersionService(...),
+            Service\LanguagePackService::class => self::getLanguagePackService(...),
+            Service\LateBootService::class => self::getLateBootService(...),
+            Service\LoadTcaService::class => self::getLoadTcaService(...),
+            Service\SilentConfigurationUpgradeService::class => self::getSilentConfigurationUpgradeService(...),
+            Service\SilentTemplateFileUpgradeService::class => self::getSilentTemplateFileUpgradeService(...),
+            Service\WebServerConfigurationFileService::class => self::getWebServerConfigurationFileService(...),
+            Service\DatabaseUpgradeWizardsService::class => self::getDatabaseUpgradeWizardsService(...),
+            Service\SetupService::class => self::getSetupService(...),
+            Service\SetupDatabaseService::class => self::getSetupDatabaseService(...),
+            Middleware\Installer::class => self::getInstallerMiddleware(...),
+            Middleware\Maintenance::class => self::getMaintenanceMiddleware(...),
+            Controller\EnvironmentController::class => self::getEnvironmentController(...),
+            Controller\IconController::class => self::getIconController(...),
+            Controller\InstallerController::class => self::getInstallerController(...),
+            Controller\LayoutController::class => self::getLayoutController(...),
+            Controller\LoginController::class => self::getLoginController(...),
+            Controller\MaintenanceController::class => self::getMaintenanceController(...),
+            Controller\SettingsController::class => self::getSettingsController(...),
+            Controller\UpgradeController::class => self::getUpgradeController(...),
+            Command\LanguagePackCommand::class => self::getLanguagePackCommand(...),
+            Command\UpgradeWizardRunCommand::class => self::getUpgradeWizardRunCommand(...),
+            Command\UpgradeWizardListCommand::class => self::getUpgradeWizardListCommand(...),
+            Command\SetupCommand::class => self::getSetupCommand(...),
+            Database\PermissionsCheck::class => self::getPermissionsCheck(...),
+            Mailer::class => self::getMailer(...),
         ];
     }
 
@@ -108,7 +108,7 @@ class ServiceProvider extends AbstractServiceProvider
             'backend.routes' => [ static::class, 'configureBackendRoutes' ],
             'backend.modules' => [ static::class, 'configureBackendModules' ],
             'icons' => [ static::class, 'configureIcons' ],
-            CommandRegistry::class => [ static::class, 'configureCommands' ],
+            CommandRegistry::class => self::configureCommands(...),
         ];
     }
 
-- 
GitLab