Skip to content

Commit f2097d2

Browse files
committed
Check callables too
1 parent f2d1a6e commit f2097d2

17 files changed

+156
-10
lines changed

src/Analyser/MutatingScope.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,16 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
14421442
if (array_key_exists($cacheKey, $cachedTypes)) {
14431443
$cachedClosureData = $cachedTypes[$cacheKey];
14441444

1445+
$mustUseReturnValue = TrinaryLogic::createNo();
1446+
foreach ($node->attrGroups as $attrGroup) {
1447+
foreach ($attrGroup->attrs as $attr) {
1448+
if ($attr->name->toLowerString() === 'nodiscard') {
1449+
$mustUseReturnValue = TrinaryLogic::createYes();
1450+
break;
1451+
}
1452+
}
1453+
}
1454+
14451455
return new ClosureType(
14461456
$parameters,
14471457
$cachedClosureData['returnType'],
@@ -1454,6 +1464,7 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
14541464
invalidateExpressions: $cachedClosureData['invalidateExpressions'],
14551465
usedVariables: $cachedClosureData['usedVariables'],
14561466
acceptsNamedArguments: TrinaryLogic::createYes(),
1467+
mustUseReturnValue: $mustUseReturnValue,
14571468
);
14581469
}
14591470
if (self::$resolveClosureTypeDepth >= 2) {
@@ -1656,6 +1667,16 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
16561667
];
16571668
$node->setAttribute('phpstanCachedTypes', $cachedTypes);
16581669

1670+
$mustUseReturnValue = TrinaryLogic::createNo();
1671+
foreach ($node->attrGroups as $attrGroup) {
1672+
foreach ($attrGroup->attrs as $attr) {
1673+
if ($attr->name->toLowerString() === 'nodiscard') {
1674+
$mustUseReturnValue = TrinaryLogic::createYes();
1675+
break;
1676+
}
1677+
}
1678+
}
1679+
16591680
return new ClosureType(
16601681
$parameters,
16611682
$returnType,
@@ -1668,6 +1689,7 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
16681689
invalidateExpressions: $invalidateExpressions,
16691690
usedVariables: $usedVariables,
16701691
acceptsNamedArguments: TrinaryLogic::createYes(),
1692+
mustUseReturnValue: $mustUseReturnValue,
16711693
);
16721694
} elseif ($node instanceof New_) {
16731695
if ($node->class instanceof Name) {
@@ -2716,10 +2738,12 @@ private function createFirstClassCallable(
27162738
$throwPoints = [];
27172739
$impurePoints = [];
27182740
$acceptsNamedArguments = TrinaryLogic::createYes();
2741+
$mustUseReturnValue = TrinaryLogic::createMaybe();
27192742
if ($variant instanceof CallableParametersAcceptor) {
27202743
$throwPoints = $variant->getThrowPoints();
27212744
$impurePoints = $variant->getImpurePoints();
27222745
$acceptsNamedArguments = $variant->acceptsNamedArguments();
2746+
$mustUseReturnValue = $variant->mustUseReturnValue();
27232747
} elseif ($function !== null) {
27242748
$returnTypeForThrow = $variant->getReturnType();
27252749
$throwType = $function->getThrowType();
@@ -2745,6 +2769,7 @@ private function createFirstClassCallable(
27452769
}
27462770

27472771
$acceptsNamedArguments = $function->acceptsNamedArguments();
2772+
$mustUseReturnValue = $function->mustUseReturnValue();
27482773
}
27492774

27502775
$parameters = $variant->getParameters();
@@ -2759,6 +2784,7 @@ private function createFirstClassCallable(
27592784
$throwPoints,
27602785
$impurePoints,
27612786
acceptsNamedArguments: $acceptsNamedArguments,
2787+
mustUseReturnValue: $mustUseReturnValue,
27622788
);
27632789
}
27642790

src/PhpDoc/TypeNodeResolver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ function (CallableTypeParameterNode $parameterNode) use ($nameScope, &$isVariadi
10321032
),
10331033
]);
10341034
} elseif ($mainType instanceof ClosureType) {
1035-
$closure = new ClosureType($parameters, $returnType, $isVariadic, $templateTypeMap, templateTags: $templateTags, impurePoints: $mainType->getImpurePoints(), invalidateExpressions: $mainType->getInvalidateExpressions(), usedVariables: $mainType->getUsedVariables(), acceptsNamedArguments: $mainType->acceptsNamedArguments());
1035+
$closure = new ClosureType($parameters, $returnType, $isVariadic, $templateTypeMap, templateTags: $templateTags, impurePoints: $mainType->getImpurePoints(), invalidateExpressions: $mainType->getInvalidateExpressions(), usedVariables: $mainType->getUsedVariables(), acceptsNamedArguments: $mainType->acceptsNamedArguments(), mustUseReturnValue: $mainType->mustUseReturnValue());
10361036
if ($closure->isPure()->yes() && $returnType->isVoid()->yes()) {
10371037
return new ErrorType();
10381038
}

src/Reflection/Callables/CallableParametersAcceptor.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,11 @@ public function getInvalidateExpressions(): array;
3636
*/
3737
public function getUsedVariables(): array;
3838

39+
/**
40+
* Has the #[\NoDiscard] attribute - on PHP 8.5+ if the function's return
41+
* value is unused at runtime a warning is emitted, PHPStan will emit the
42+
* warning during analysis and on older PHP versions too
43+
*/
44+
public function mustUseReturnValue(): TrinaryLogic;
45+
3946
}

src/Reflection/Callables/FunctionCallableVariant.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,9 @@ public function acceptsNamedArguments(): TrinaryLogic
168168
return $this->function->acceptsNamedArguments();
169169
}
170170

171+
public function mustUseReturnValue(): TrinaryLogic
172+
{
173+
return $this->function->mustUseReturnValue();
174+
}
175+
171176
}

src/Reflection/ExtendedCallableFunctionVariant.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public function __construct(
3636
private array $invalidateExpressions,
3737
private array $usedVariables,
3838
private TrinaryLogic $acceptsNamedArguments,
39+
private TrinaryLogic $mustUseReturnValue,
3940
)
4041
{
4142
parent::__construct(
@@ -80,4 +81,9 @@ public function acceptsNamedArguments(): TrinaryLogic
8081
return $this->acceptsNamedArguments;
8182
}
8283

84+
public function mustUseReturnValue(): TrinaryLogic
85+
{
86+
return $this->mustUseReturnValue;
87+
}
88+
8389
}

src/Reflection/GenericParametersAcceptorResolver.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ public static function resolve(array $argTypes, ParametersAcceptor $parametersAc
128128
$originalParametersAcceptor->getInvalidateExpressions(),
129129
$originalParametersAcceptor->getUsedVariables(),
130130
$originalParametersAcceptor->acceptsNamedArguments(),
131+
$originalParametersAcceptor->mustUseReturnValue(),
131132
);
132133
}
133134

src/Reflection/InaccessibleMethod.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,9 @@ public function acceptsNamedArguments(): TrinaryLogic
8888
return $this->methodReflection->acceptsNamedArguments();
8989
}
9090

91+
public function mustUseReturnValue(): TrinaryLogic
92+
{
93+
return TrinaryLogic::createMaybe();
94+
}
95+
9196
}

src/Reflection/ParametersAcceptorSelector.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ public static function combineAcceptors(array $acceptors): ExtendedParametersAcc
639639
$invalidateExpressions = [];
640640
$usedVariables = [];
641641
$acceptsNamedArguments = TrinaryLogic::createNo();
642+
$mustUseReturnValue = TrinaryLogic::createMaybe();
642643

643644
foreach ($acceptors as $acceptor) {
644645
$returnTypes[] = $acceptor->getReturnType();
@@ -655,6 +656,7 @@ public static function combineAcceptors(array $acceptors): ExtendedParametersAcc
655656
$invalidateExpressions = array_merge($invalidateExpressions, $acceptor->getInvalidateExpressions());
656657
$usedVariables = array_merge($usedVariables, $acceptor->getUsedVariables());
657658
$acceptsNamedArguments = $acceptsNamedArguments->or($acceptor->acceptsNamedArguments());
659+
$mustUseReturnValue = $mustUseReturnValue->or($acceptor->mustUseReturnValue());
658660
}
659661
$isVariadic = $isVariadic || $acceptor->isVariadic();
660662

@@ -761,6 +763,7 @@ public static function combineAcceptors(array $acceptors): ExtendedParametersAcc
761763
$invalidateExpressions,
762764
$usedVariables,
763765
$acceptsNamedArguments,
766+
$mustUseReturnValue,
764767
);
765768
}
766769

@@ -797,6 +800,7 @@ private static function wrapAcceptor(ParametersAcceptor $acceptor): ExtendedPara
797800
$acceptor->getInvalidateExpressions(),
798801
$acceptor->getUsedVariables(),
799802
$acceptor->acceptsNamedArguments(),
803+
$acceptor->mustUseReturnValue(),
800804
);
801805
}
802806

src/Reflection/ResolvedFunctionVariantWithCallable.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public function __construct(
2828
private array $invalidateExpressions,
2929
private array $usedVariables,
3030
private TrinaryLogic $acceptsNamedArguments,
31+
private TrinaryLogic $mustUseReturnValue,
3132
)
3233
{
3334
}
@@ -112,4 +113,9 @@ public function acceptsNamedArguments(): TrinaryLogic
112113
return $this->acceptsNamedArguments;
113114
}
114115

116+
public function mustUseReturnValue(): TrinaryLogic
117+
{
118+
return $this->mustUseReturnValue;
119+
}
120+
115121
}

src/Reflection/TrivialParametersAcceptor.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,9 @@ public function acceptsNamedArguments(): TrinaryLogic
9898
return TrinaryLogic::createYes();
9999
}
100100

101+
public function mustUseReturnValue(): TrinaryLogic
102+
{
103+
return TrinaryLogic::createMaybe();
104+
}
105+
101106
}

0 commit comments

Comments
 (0)