Skip to content

Conversation

@HypeMC
Copy link
Member

@HypeMC HypeMC commented Dec 12, 2025

Q A
Branch? 7.3
Bug fix? yes
New feature? no
Deprecations? no
Issues -
License MIT

When using a combination of #[AutowireCallable] and a service locator, services may be incorrectly inlined, resulting in a broken compiled container. For example, before and after the fix (namespaces removed for readability):

/**
 * Gets the private 'Listener1' shared autowired service.
 *
 * @return \Listener1
 */
protected static function getListener1Service($container)
{
-   return $container->privates['Listener1'] = new \Listener1(($container->services['MyInlineService'] ?? $container->get('MyInlineService'))->someMethod1(...));
+   return $container->privates['Listener1'] = new \Listener1(($container->privates['MyInlineService'] ??= new \MyInlineService())->someMethod1(...));
}

/**
 * Gets the private 'Listener2' shared autowired service.
 *
 * @return \Listener2
 */
protected static function getListener2Service($container)
{
-   return $container->privates['Listener2'] = new \Listener2((new \MyInlineService())->someMethod1(...), new \stdClass());
+   return $container->privates['Listener2'] = new \Listener2(($container->privates['MyInlineService'] ??= new \MyInlineService())->someMethod2(...), new \stdClass());
}

The getListener1Service() method was broken because $container->get('MyInlineService') throws an exception:

Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: The "Symfony\Component\DependencyInjection\Tests\Compiler\MyInlineService" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.

The issue is not present in 6.4.

} else {
$container->removeDefinition($id);
$analyzedContainer->removeDefinition($id);
if (!isset($this->autowireInline[$id])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doing this special case here not removing the definition ? If it can be inlined, there is no reason to keep it.
Maybe the fix is to avoid considering it as inlineable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is not that the service itself is being inlined. The real problem occurs when one of the service's arguments is an AutowireCallable. If the parent service is removed, then \count($srcIds) for the argument service becomes 1, which is incorrect. As a result, the argument service is inlined when it should not be.


$this->assertStringEqualsFile(self::$fixturesPath.'/php/autowire_callable_with_service_locator.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_AutowireCallable_With_ServiceLocator']));

require self::$fixturesPath.'/php/autowire_callable_with_service_locator.php';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about using an inline eval and skip committing the generated code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@HypeMC HypeMC force-pushed the fix-autowirecallable-with-servicelocator branch from 6b5f7d9 to 3b22fc2 Compare December 14, 2025 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants