diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
index bb67eb16794a..f3c4b593cccc 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
@@ -34,6 +34,8 @@ class ResolveBindingsPass extends AbstractRecursivePass
*/
public function process(ContainerBuilder $container)
{
+ $this->usedBindings = $container->getRemovedBindingIds();
+
try {
parent::process($container);
diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
index 0c1966a42e25..72307464a7b5 100644
--- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
@@ -123,6 +123,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
private $removedIds = [];
+ private $removedBindingIds = [];
+
private static $internalTypes = [
'int' => true,
'float' => true,
@@ -1504,6 +1506,35 @@ public function normalizeId($id)
return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || isset($this->removedIds[$id]) ? $id : parent::normalizeId($id);
}
+ /**
+ * Gets removed binding ids.
+ *
+ * @return array
+ *
+ * @internal
+ */
+ public function getRemovedBindingIds()
+ {
+ return $this->removedBindingIds;
+ }
+
+ /**
+ * Adds a removed binding id.
+ *
+ * @param int $id
+ *
+ * @internal
+ */
+ public function addRemovedBindingIds($id)
+ {
+ if ($this->hasDefinition($id)) {
+ foreach ($this->getDefinition($id)->getBindings() as $key => $binding) {
+ list(, $bindingId) = $binding->getValues();
+ $this->removedBindingIds[(int) $bindingId] = true;
+ }
+ }
+ }
+
/**
* Returns the Service Conditionals.
*
diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServiceConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServiceConfigurator.php
index 12054cad0c02..21b1669d09ec 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServiceConfigurator.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServiceConfigurator.php
@@ -59,6 +59,8 @@ public function __destruct()
{
parent::__destruct();
+ $this->container->addRemovedBindingIds($this->id);
+
if (!$this->definition instanceof ChildDefinition) {
$this->container->setDefinition($this->id, $this->definition->setInstanceofConditionals($this->instanceof));
} else {
diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
index a428c6e35f6c..0dd1a3d8bded 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
@@ -91,6 +91,8 @@ public function registerClasses(Definition $prototype, $namespace, $resource, $e
*/
protected function setDefinition($id, Definition $definition)
{
+ $this->container->addRemovedBindingIds($id);
+
if ($this->isLoadingInstanceof) {
if (!$definition instanceof ChildDefinition) {
throw new InvalidArgumentException(sprintf('Invalid type definition "%s": ChildDefinition expected, "%s" given.', $id, \get_class($definition)));
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Bar.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Bar.php
index 83f2da12a70a..1aaca2f1560c 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Bar.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Bar.php
@@ -13,8 +13,11 @@
class Bar implements BarInterface
{
+ public $quz;
+
public function __construct($quz = null, \NonExistent $nonExistent = null, BarInterface $decorated = null, array $foo = [])
{
+ $this->quz = $quz;
}
public static function create(\NonExistent $nonExistent = null, $factory = null)
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/defaults_bindings.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/defaults_bindings.xml
new file mode 100644
index 000000000000..d943dfad2d7f
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/defaults_bindings.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ value
+
+ value
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/defaults_bindings2.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/defaults_bindings2.xml
new file mode 100644
index 000000000000..db41330f854e
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/defaults_bindings2.xml
@@ -0,0 +1,10 @@
+
+
+
+
+ overridden
+
+
+
+
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/defaults_bindings.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/defaults_bindings.yml
new file mode 100644
index 000000000000..ca5e5048de12
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/defaults_bindings.yml
@@ -0,0 +1,11 @@
+services:
+ _defaults:
+ bind:
+ $quz: value
+ $foo: [value]
+
+ bar:
+ class: Symfony\Component\DependencyInjection\Tests\Fixtures\Bar
+
+ foo:
+ class: stdClass
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/defaults_bindings2.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/defaults_bindings2.yml
new file mode 100644
index 000000000000..01fc5af62458
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/defaults_bindings2.yml
@@ -0,0 +1,7 @@
+services:
+ _defaults:
+ bind:
+ $quz: overridden
+
+ bar:
+ class: Symfony\Component\DependencyInjection\Tests\Fixtures\Bar
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php
index d89887acca9e..03376a641dcc 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php
@@ -17,6 +17,7 @@
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Resource\GlobResource;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
@@ -820,4 +821,20 @@ public function testTsantosContainer()
$dump = $dumper->dump();
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_tsantos.php', $dumper->dump());
}
+
+ /**
+ * The pass may throw an exception, which will cause the test to fail.
+ */
+ public function testOverriddenDefaultsBindings()
+ {
+ $container = new ContainerBuilder();
+
+ $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
+ $loader->load('defaults_bindings.xml');
+ $loader->load('defaults_bindings2.xml');
+
+ (new ResolveBindingsPass())->process($container);
+
+ $this->assertSame('overridden', $container->get('bar')->quz);
+ }
}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
index 7bcf0ec05758..05521bf7846f 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
@@ -17,6 +17,7 @@
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Resource\GlobResource;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
@@ -732,4 +733,20 @@ public function testBindings()
'$factory' => 'factory',
], array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings()));
}
+
+ /**
+ * The pass may throw an exception, which will cause the test to fail.
+ */
+ public function testOverriddenDefaultsBindings()
+ {
+ $container = new ContainerBuilder();
+
+ $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
+ $loader->load('defaults_bindings.yml');
+ $loader->load('defaults_bindings2.yml');
+
+ (new ResolveBindingsPass())->process($container);
+
+ $this->assertSame('overridden', $container->get('bar')->quz);
+ }
}