Skip to content

Commit 277be5d

Browse files
committed
Report NoDiscard above never return type + implicit void methods reported too
1 parent 55c990e commit 277be5d

13 files changed

+101
-12
lines changed

src/Rules/FunctionDefinitionCheck.php

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use PHPStan\ShouldNotHappenException;
3232
use PHPStan\Type\ConditionalTypeForParameter;
3333
use PHPStan\Type\Generic\TemplateType;
34+
use PHPStan\Type\NeverType;
3435
use PHPStan\Type\NonexistentParentClassType;
3536
use PHPStan\Type\ParserNodeTypeToPHPStanType;
3637
use PHPStan\Type\Type;
@@ -109,7 +110,7 @@ public function checkAnonymousFunction(
109110
string $unionTypesMessage,
110111
string $unresolvableParameterTypeMessage,
111112
string $unresolvableReturnTypeMessage,
112-
string $noDiscardVoidReturnMessage,
113+
string $noDiscardReturnTypeMessage,
113114
): array
114115
{
115116
$errors = [];
@@ -202,11 +203,14 @@ public function checkAnonymousFunction(
202203
if ($returnTypeNode === null) {
203204
return $errors;
204205
}
205-
if ($returnTypeNode instanceof Identifier && $returnTypeNode->name === 'void') {
206+
if (
207+
$returnTypeNode instanceof Identifier
208+
&& in_array($returnTypeNode->toLowerString(), ['void', 'never'], true)
209+
) {
206210
foreach ($attribGroups as $attribGroup) {
207211
foreach ($attribGroup->attrs as $attrib) {
208212
if (strtolower($attrib->name->name) === 'nodiscard') {
209-
$errors[] = RuleErrorBuilder::message($noDiscardVoidReturnMessage)
213+
$errors[] = RuleErrorBuilder::message(sprintf($noDiscardReturnTypeMessage, $returnTypeNode->toString()))
210214
->line($returnTypeNode->getStartLine())
211215
->identifier('attribute.target')
212216
->build();
@@ -349,7 +353,7 @@ private function checkParametersAcceptor(
349353
string $templateTypeMissingInParameterMessage,
350354
string $unresolvableParameterTypeMessage,
351355
string $unresolvableReturnTypeMessage,
352-
string $noDiscardVoidReturnMessage,
356+
string $noDiscardReturnTypeMessage,
353357
): array
354358
{
355359
$errors = [];
@@ -495,11 +499,12 @@ private function checkParametersAcceptor(
495499
}
496500
}
497501
if ($parametersAcceptor->mustUseReturnValue()->yes()) {
498-
$returnType = $functionNode->getReturnType();
499-
if ($returnType instanceof Identifier
500-
&& $returnType->name === 'void'
502+
$returnType = $parametersAcceptor->getReturnType();
503+
if (
504+
$returnType->isVoid()->yes()
505+
|| ($returnType instanceof NeverType && $returnType->isExplicit())
501506
) {
502-
$errors[] = RuleErrorBuilder::message($noDiscardVoidReturnMessage)
507+
$errors[] = RuleErrorBuilder::message(sprintf($noDiscardReturnTypeMessage, $returnType->describe(VerbosityLevel::typeOnly())))
503508
->line($returnTypeNode->getStartLine())
504509
->identifier('attribute.target')
505510
->build();

src/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public function processNode(Node $node, Scope $scope): array
5252
'Anonymous function uses native union types but they\'re supported only on PHP 8.0 and later.',
5353
'Parameter $%s of anonymous function has unresolvable native type.',
5454
'Anonymous function has unresolvable native return type.',
55-
'Attribute NoDiscard cannot be used on void anonymous function.',
55+
'Attribute NoDiscard cannot be used on %s anonymous function.',
5656
));
5757
}
5858

src/Rules/Functions/ExistingClassesInClosureTypehintsRule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function processNode(Node $node, Scope $scope): array
3737
'Anonymous function uses native union types but they\'re supported only on PHP 8.0 and later.',
3838
'Parameter $%s of anonymous function has unresolvable native type.',
3939
'Anonymous function has unresolvable native return type.',
40-
'Attribute NoDiscard cannot be used on void anonymous function.',
40+
'Attribute NoDiscard cannot be used on %s anonymous function.',
4141
);
4242
}
4343

src/Rules/Functions/ExistingClassesInTypehintsRule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public function processNode(Node $node, Scope $scope): array
5454
$functionName,
5555
),
5656
sprintf(
57-
'Attribute NoDiscard cannot be used on void function %s().',
57+
'Attribute NoDiscard cannot be used on %%s function %s().',
5858
$functionName,
5959
),
6060
);

src/Rules/Methods/ExistingClassesInTypehintsRule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public function processNode(Node $node, Scope $scope): array
6565
$methodName,
6666
),
6767
sprintf(
68-
'Attribute NoDiscard cannot be used on void method %s::%s().',
68+
'Attribute NoDiscard cannot be used on %%s method %s::%s().',
6969
$className,
7070
$methodName,
7171
),

tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,10 @@ public function testNoDiscardVoid(): void
331331
'Attribute NoDiscard cannot be used on void anonymous function.',
332332
10,
333333
],
334+
[
335+
'Attribute NoDiscard cannot be used on never anonymous function.',
336+
15,
337+
],
334338
]);
335339
}
336340

tests/PHPStan/Rules/Functions/ExistingClassesInClosureTypehintsRuleTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,10 @@ public function testNoDiscardVoid(): void
360360
'Attribute NoDiscard cannot be used on void anonymous function.',
361361
5,
362362
],
363+
[
364+
'Attribute NoDiscard cannot be used on never anonymous function.',
365+
10,
366+
],
363367
]);
364368
}
365369

tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,10 @@ public function testNoDiscardVoid(): void
496496
'Attribute NoDiscard cannot be used on void function TestFunctionTypehints\nothing().',
497497
6,
498498
],
499+
[
500+
'Attribute NoDiscard cannot be used on never function TestFunctionTypehints\returnNever().',
501+
10,
502+
],
499503
]);
500504
}
501505

tests/PHPStan/Rules/Functions/data/arrow-function-typehints-nodiscard.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,9 @@ public function doFoo()
1010
#[\NoDiscard] fn(): void => true;
1111
}
1212

13+
public function doBar()
14+
{
15+
#[\NoDiscard] fn(): never => true;
16+
}
17+
1318
}

tests/PHPStan/Rules/Functions/data/closure-typehints-nodiscard.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@
66
{
77

88
};
9+
10+
$callbackNever = #[\NoDiscard] function (): never
11+
{
12+
13+
};

0 commit comments

Comments
 (0)