Commit 47eefa4
committed
bug #45629 [FrameworkBundle] Fix container:lint and #[Autoconfigure(binds: ...)] failing (LANGERGabrielle)
This PR was merged into the 5.4 branch.
Discussion
----------
[FrameworkBundle] Fix container:lint and #[Autoconfigure(binds: ...)] failing
| Q | A
| ------------- | ---
| Branch? | 5.4
| Bug fix? | yes
| New feature? | no
| Deprecations? | no
| Tickets |
| License | MIT
| Doc PR |
# Description
Running `container:lint` when a service uses `#[Autoconfigure(binds: ['$myDependency' => {...})]` raises an error :
```
[ERROR] A binding is configured for an argument named "$myDependency" under
"_instanceof" in file "/{...}/MyService.php", but no
corresponding argument has been found. It may be unused and should be
removed, or it may have a typo.
```
# How to reproduce
Given a service
```php
#[Autoconfigure(bind: ['$myDependency' => '`@app`.my_dependency'])]
class MyService
{
public function __construct(MyDependency $myDependency)
{
}
}
```
``@app`.my_dependency` is correctly injected into `MyService`. But when running `container:lint` **with the container dumped** (`App_KernelDevDebugContainer.xml` is present and up to date), it raises an error.
This only happens with `#[Autoconfigure]`. A similar configuration but using `services.yaml` works as expected :
```yaml
__instanceof:
App\MyService:
binds:
$myDependency: '`@app`.my_dependency'
```
# Explanation of the issue
1. [`RegisterAutoconfigureAttributesPass` parses the `#[Autoconfigure]` and registers its binding](https://github.com/symfony/symfony/blob/08fa74a16c84895575e305b2a7ee3a03e371f79b/src/Symfony/Component/DependencyInjection/Compiler/RegisterAutoconfigureAttributesPass.php#L71).
2. [`ResolveBindingsPass` reads the binding and uses it to configure the service `arguments`](https://github.com/symfony/symfony/blob/1255cfffc260500adbfb3268b8f6c644e8bc43dd/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php#L223).
3. The container is dumped, with `App_KernelDevDebugContainer.xml` containing
```xml
<service id="App\MyService" class="App\MyService" autowire="true" autoconfigure="true">
<argument type="service" id="app.my_dependency"/>
</service>
```
4. [`ContainerLintCommand` then creates a container from the dump](https://github.com/symfony/symfony/blob/08fa74a16c84895575e305b2a7ee3a03e371f79b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php#L104).
5. [The container is compiled](https://github.com/symfony/symfony/blob/08fa74a16c84895575e305b2a7ee3a03e371f79b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php#L65). Since `Kernel::initializeBundles()` is not called, only the [base passes](https://github.com/symfony/symfony/blob/60ce5a3dfbd90fad60cd39fcb3d7bf7888a48659/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php#L42) are used.
6. [`RegisterAutoconfigureAttributesPass` parses the `#[Autoconfigure]` and registers its binding](https://github.com/symfony/symfony/blob/08fa74a16c84895575e305b2a7ee3a03e371f79b/src/Symfony/Component/DependencyInjection/Compiler/RegisterAutoconfigureAttributesPass.php#L71), **again**.
7. [`ResolveBindingsPass` sees that the service already has an `argument` (from the xml dump from the first `ResolveBindingsPass`)](https://github.com/symfony/symfony/blob/1255cfffc260500adbfb3268b8f6c644e8bc43dd/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php#L181). This mean that the binding is **not** used this time, [and it is never removed from `$unusedBindings`](https://github.com/symfony/symfony/blob/1255cfffc260500adbfb3268b8f6c644e8bc43dd/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php#L126).
8. [The error is then thrown](https://github.com/symfony/symfony/blob/1255cfffc260500adbfb3268b8f6c644e8bc43dd/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php#L76).
# Explanation of the fix
This fix removes the passes that already processed the dumped container.
A more future proof fix would be symfony/symfony@209516b, but it would require changes to `DependencyInjection`.
Both fixes have been tested on a mid size Symfony application.
Commits
-------
309998b94d [FrameworkBundle] Fix compiler passes processing a container twice when it's loaded from the debug dumpFile tree
2 files changed
+8
-0
lines changed- Command
2 files changed
+8
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
56 | 60 | | |
57 | 61 | | |
58 | 62 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
118 | 118 | | |
119 | 119 | | |
120 | 120 | | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
121 | 125 | | |
122 | 126 | | |
123 | 127 | | |
| |||
0 commit comments