Skip to content

Commit f364362

Browse files
committed
Improve UB in exceptions
1 parent b8b20d6 commit f364362

4 files changed

Lines changed: 13 additions & 23 deletions

File tree

src/Exception/Definition/Template/OneOfTemplateArgumentsCountException.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function __construct(
1717
*/
1818
public readonly int $passedArgumentsCount,
1919
/**
20-
* @var list<int<0, max>>
20+
* @var non-empty-list<int<0, max>>
2121
*/
2222
public readonly array $expectedArgumentCountVariants,
2323
NamedTypeNode $type,
@@ -56,6 +56,7 @@ public static function becauseArgumentsCountDoesNotMatch(
5656
$template = 'Type "{{type}}" only accepts {{expectedArgumentCountVariants}}'
5757
. ' template argument(s), but {{passedArgumentsCount}} were passed';
5858

59+
/** @var non-empty-array<array-key, int<0, max>> $variants */
5960
return new self(
6061
passedArgumentsCount: $passedArgumentsCount,
6162
expectedArgumentCountVariants: \array_values($variants),

src/Exception/Definition/Template/TemplateArgumentException.php

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,19 @@ public function __construct(
2424
int $code = 0,
2525
?\Throwable $previous = null,
2626
) {
27-
$this->index = self::getArgumentIndex($argument, $type);
27+
$this->index = $this->getArgumentIndex($type, $argument);
2828

2929
parent::__construct($type, $template, $code, $previous);
3030
}
3131

32-
/**
33-
* @return int<0, max>
34-
*/
35-
private static function getArgumentIndex(TemplateArgumentNode $argument, NamedTypeNode $type): int
32+
private function getArgumentIndex(NamedTypeNode $type, TemplateArgumentNode $argument): int
3633
{
37-
$index = 0;
38-
39-
if ($type->arguments === null) {
40-
return $index;
41-
}
42-
43-
foreach ($type->arguments as $actual) {
44-
if ($actual === $argument) {
45-
return $index + 1;
46-
}
34+
$index = $type->arguments?->findIndex($argument);
4735

48-
++$index;
49-
}
36+
assert($index !== null, new \InvalidArgumentException(
37+
'Template argument is not a part of passed type',
38+
));
5039

51-
return $index;
40+
return $index + 1;
5241
}
5342
}

tests/Exception/Definition/InvalidTemplateArgumentTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ public function testInvalidArgumentGiven(): void
3838
#[TestDox('[undefined behaviour] all works if pass an non-node\'s argument')]
3939
public function testOfNonOwnArgument(): void
4040
{
41-
$this->expectException(InvalidTemplateArgumentException::class);
42-
$this->expectExceptionMessage('Passed template argument #0 of type another-type must be of type string, but T given');
41+
$this->skipIfAssertionsDisabled();
42+
$this->expectExceptionMessage('Template argument is not a part of passed type');
4343

4444
$type = self::parse('int<T>');
4545
assert($type instanceof NamedTypeNode);

tests/Exception/Definition/TemplateArgumentHintsNotSupportedTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ public function testManyArgumentsPassedWithGenericType(): void
3636
#[TestDox('[undefined behaviour] all works if pass an non-node\'s argument')]
3737
public function testOfNonOwnArgument(): void
3838
{
39-
$this->expectException(TemplateArgumentHintsNotSupportedException::class);
40-
$this->expectExceptionMessage('Template argument #1 (T) of "another-type<out T>" does not support any hints, but "in" were passed');
39+
$this->skipIfAssertionsDisabled();
40+
$this->expectExceptionMessage('Template argument is not a part of passed type');
4141

4242
$type = self::parse('int<in T>');
4343
assert($type instanceof NamedTypeNode);

0 commit comments

Comments
 (0)