You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
bug #22254 [DI] Don't use auto-registered services to populate type-candidates (nicolas-grekas)
This PR was merged into the 2.8 branch.
Discussion
----------
[DI] Don't use auto-registered services to populate type-candidates
| Q | A
| ------------- | ---
| Branch? | 2.8
| Bug fix? | yes
| New feature? | no
| BC breaks? | no (every bug fix is a bc break, isn't it?)
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #22162, ~~#21658~~
| License | MIT
| Doc PR | symfony/symfony-docs#... <!--highly recommended for new features-->
Alternative to #22170 and ~~#21665~~.
The core issue fixed here is that auto-registered services should *not* be used as type-candidates.
The culprit is this line:
`$this->populateAvailableType($argumentId, $argumentDefinition);`
Doing so creates a series of wtf-issues (the linked ones), with no simple fixes (the linked PRs are just dealing with the simplest cases, but the real fix would require a reboot of autowiring for every newly discovered types.)
The other changes accommodate for the removal of the population of the `types` property, and fix a few other issues found along the way:
- variadic constructors
- empty strings injection
- tail args removal when they match the existing defaults
Commits
-------
992c677 [DI] Don't use auto-registered services to populate type-candidates
thrownewRuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $type, $id, $classOrInterface, $matchingServices));
55
-
}
56
-
}
57
48
} catch (\Exception$e) {
58
49
} catch (\Throwable$e) {
59
50
}
@@ -66,7 +57,7 @@ public function process(ContainerBuilder $container)
66
57
$this->definedTypes = array();
67
58
$this->types = null;
68
59
$this->notGuessableTypes = array();
69
-
$this->usedTypes = array();
60
+
$this->autowired = array();
70
61
71
62
if (isset($e)) {
72
63
throw$e;
@@ -92,47 +83,56 @@ private function completeDefinition($id, Definition $definition)
92
83
if (!$constructor = $reflectionClass->getConstructor()) {
93
84
return;
94
85
}
86
+
$parameters = $constructor->getParameters();
87
+
if (method_exists('ReflectionMethod', 'isVariadic') && $constructor->isVariadic()) {
if (array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
99
94
continue;
100
95
}
101
96
102
97
try {
103
98
if (!$typeHint = $parameter->getClass()) {
99
+
if (isset($arguments[$index])) {
100
+
continue;
101
+
}
102
+
104
103
// no default value? Then fail
105
104
if (!$parameter->isOptional()) {
106
105
thrownewRuntimeException(sprintf('Unable to autowire argument index %d ($%s) for the service "%s". If this is an object, give it a type-hint. Otherwise, specify this argument\'s value explicitly.', $index, $parameter->name, $id));
@@ -148,6 +148,16 @@ private function completeDefinition($id, Definition $definition)
148
148
$arguments[$index] = $value;
149
149
}
150
150
151
+
if ($parameters && !isset($arguments[++$index])) {
152
+
while (0 <= --$index) {
153
+
$parameter = $parameters[$index];
154
+
if (!$parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== $arguments[$index]) {
155
+
break;
156
+
}
157
+
unset($arguments[$index]);
158
+
}
159
+
}
160
+
151
161
// it's possible index 1 was set, then index 0, then 2, etc
152
162
// make sure that we re-order so they're injected as expected
153
163
ksort($arguments);
@@ -252,13 +262,11 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
252
262
thrownewRuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface));
* @expectedExceptionMEssage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". Multiple services exist for this interface (autowired.Symfony\Component\DependencyInjection\Tests\Compiler\CollisionA, autowired.Symfony\Component\DependencyInjection\Tests\Compiler\CollisionB).
0 commit comments