Issue 1:
Q
A

Bug report?
yes

Feature request?
no

BC Break report?
no

RFC?
no

Symfony version
3.3

When you define no arguments, autowiring will give you a very precise error. However, if you manually define arguments that come after that using named arguments, the error will become extremely cryptic.

Given the following PHP:

namespace Hostnet;

interface TestInterface {}

class TestOne implements TestInterface {}
class TestTwo implements TestInterface {}

class TestDependency {}

class TestClass
{
public function __construct(
TestOne $testOne,
TestInterface $testTwo,
TestDependency $testDependency
) {}
}

Using this configuration (100% autowiring):

services:
Hostnet\TestClass: ~
Hostnet\TestOne: ~
Hostnet\TestTwo: ~
Hostnet\TestDependency:
public: true

I will get the descriptive error:

AutowiringFailedException

Cannot autowire service "Hostnet\TestClass": argument "$testTwo" of
method "__construct()" references interface "Hostnet\TestInterface" but
no such service exists. You should maybe alias this interface to one of
these existing services: "Hostnet\TestOne", "Hostnet\TestTwo".

When I manually wire 1 argument that's positioned after the dependency that will fail (last argument in this case):

services:
Hostnet\TestClass:
$testDependency: '@Hostnet\TestDependency'
Hostnet\TestOne: ~
Hostnet\TestTwo: ~
Hostnet\TestDependency:
public: true

This results in a crpytic error:

RuntimeException

Invalid constructor argument 3 for service "Hostnet\TestClass": argument 1
must be defined before. Check your service definition.

Issue 2:
Q
A

Bug report?
yes

Feature request?
no

BC Break report?
no

RFC?
no

Symfony version
3.3.*

From a training today :). Suppose this class:

class MyCoolClass
{
public function __construct(Logger $logger, $isDebug)
{

}
}

Because Logger is the wrong type-hint, I should receive this error:

Cannot autowire service "AppBundle\EventListener\MyCoolClass": argument "$logger" of method "__construct()" references class "Monolog\Logger" but no such service exists...

And at first, I do! But suppose I specify the $isDebug argument:

services:
AppBundle\Service\MyCoolClass:
arguments:
$isDebug: true

As soon as this arg is specified the error changes:

Invalid constructor argument 2 for service "AppBundle\EventListener\MyCoolClass": argument 1 must be defined before.

The problem is:

A) AutowirePass correctly throws an AutowiringFailedException due to the bad Logger type-hint. But, exceptions are not thrown in this class, but stored for later

B) Because argument 1 appears to be missing, CheckArgumentsValidityPass throws the above exception

C) The AutowireExceptionPass - which would normally throw the exception from (A), is never called - because (B) already threw its exception.

The correct behavior is to always throw the first exception about the Logger class. But, I'm not sure how to do this. AutowirePass purposefully does not throw exceptions... because it waits to make sure the service wasn't removed from the container. But in this case, CheckArgumentsValidityPass steps in early and throws this other, less clear exception. It has no idea that the true exception is just waiting for the "ok" that the service wasn't removed.

I'm open to ideas... :). In general, the passes are becoming a bit more dependent on each other, and that's complicating things.

Cheers!