Repository: symfony/symfony
File: src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php (PHP)

Code before:

                return $value;
            };

            if ($checkAttributes) {
                foreach ($parameter->getAttributes(Autowire::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
                    $attribute = $attribute->newInstance();
                    $invalidBehavior = $parameter->allowsNull() ? ContainerInterface::NULL_ON_INVALID_REFERENCE : ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE;

                    try {
                        $value = $this->processValue(new TypedReference($type ?: '?', $type ?: 'mixed', $invalidBehavior, $name, [$attribute, ...$target]));
                    } catch (ParameterNotFoundException $e) {
                        if (!$parameter->isDefaultValueAvailable()) {
                            throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e);
                        }
                        $arguments[$index] = clone $this->defaultArgument;
                        $arguments[$index]->value = $parameter->getDefaultValue();

                        continue 2;
                    }

                    if ($attribute instanceof AutowireCallable) {
                        $value = $attribute->buildDefinition($value, $type, $parameter);
                    } elseif ($lazy = $attribute->lazy) {
                        if ($this->container->has($type)) {
                            $type = $this->container->findDefinition($type)->getClass();
                        }
                        $definition = (new Definition($type))
                            ->setFactory('current')
                            ->setArguments([[$value ??= $getValue()]])
                            ->setLazy(true);

                        if (!\is_array($lazy)) {
                            if (str_contains($type, '|')) {
                                throw new AutowiringFailedException($this->currentId, sprintf('Cannot use #[Autowire] with option "lazy: true" on union types for service "%s"; set the option to the interface(s) that should be proxied instead.', $this->currentId));
                            }
                            $lazy = str_contains($type, '&') ? explode('&', $type) : [];
                        }

                        if ($lazy) {
                            if (!class_exists($type) && !interface_exists($type, false)) {
                                $definition->setClass('object');
                            }
                            foreach ($lazy as $v) {
                                $definition->addTag('proxy', ['interface' => $v]);
                            }
                        }

                        if ($definition->getClass() !== (string) $value || $definition->getTag('proxy')) {
                            $value .= '.'.$this->container->hash([$definition->getClass(), $definition->getTag('proxy')]);
                        }

Review comment (suggestion):
I don't think this should be done for the case where `lazy` is an array specifying the exact interfaces that should be proxied

Code after:

                if (1 < \count($attributes)) {
                    throw new AutowiringFailedException($this->currentId, 'Using both attributes #[Lazy] and #[Autowire] on an argument is not allowed; use the "lazy" parameter of #[Autowire] instead.');
                }

                foreach ($attributes as $attribute) {
                    $attribute = $attribute->newInstance();
                    $value = $attribute instanceof Autowire ? $attribute->value : null;

                    if (\is_string($value) && str_starts_with($value, '%env(') && str_ends_with($value, ')%')) {
                        if ($parameter->getType() instanceof \ReflectionNamedType && 'bool' === $parameter->getType()->getName() && !str_starts_with($value, '%env(bool:')) {
                            $attribute = new Autowire(substr_replace($value, 'bool:', 5, 0));
                        }
                        if ($parameter->isDefaultValueAvailable() && $parameter->allowsNull() && null === $parameter->getDefaultValue() && !preg_match('/(^|:)default:/', $value)) {
                            $attribute = new Autowire(substr_replace($value, 'default::', 5, 0));
                        }
                    }

                    $invalidBehavior = $parameter->allowsNull() ? ContainerInterface::NULL_ON_INVALID_REFERENCE : ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE;

                    try {
                        $value = $this->processValue(new TypedReference($type ?: '?', $type ?: 'mixed', $invalidBehavior, $name, [$attribute, ...$target]));
                    } catch (ParameterNotFoundException $e) {
                        if (!$parameter->isDefaultValueAvailable()) {
                            throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e);
                        }
                        $arguments[$index] = clone $defaultArgument;
                        $arguments[$index]->value = $parameter->getDefaultValue();

                        continue 2;
                    }

                    if ($attribute instanceof AutowireInline) {
                        $value = $attribute->buildDefinition($value, $type, $parameter);
                        $value = $this->doProcessValue($value);
                    } elseif ($lazy = $attribute->lazy) {
                        $value ??= $getValue();
                        if ($this->container->has($value->getType())) {
                            $type = $this->container->findDefinition($value->getType())->getClass();
                        }
                        $definition = (new Definition($type))
                            ->setFactory('current')
                            ->setArguments([[$value]])
                            ->setLazy(true);

                        if (!\is_array($lazy)) {
                            if (str_contains($type, '|')) {
                                throw new AutowiringFailedException($this->currentId, \sprintf('Cannot use #[Autowire] with option "lazy: true" on union types for service "%s"; set the option to the interface(s) that should be proxied instead.', $this->currentId));
                            }
                            $lazy = str_contains($type, '&') ? explode('&', $type) : [];
                        }