Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/Rules/IssetCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,16 @@ static function (Type $type) use ($typeMessageCallback): ?string {
}

if ($expr instanceof Expr\NullsafePropertyFetch) {
// For ?? the nullsafe operator is needed when the object can be null,
// because ?? does not catch TypeError from property access on null.
// isset()/empty() handle null objects natively so ?-> is truly redundant there.
if ($identifier === 'nullCoalesce') {
$varType = $this->treatPhpDocTypesAsCertain ? $scope->getScopeType($expr->var) : $scope->getScopeNativeType($expr->var);
if (!$varType->isNull()->no()) {
return null;
}
}

if ($expr->name instanceof Node\Identifier) {
return RuleErrorBuilder::message(sprintf('Using nullsafe property access "?->%s" %s is unnecessary. Use -> instead.', $expr->name->name, $operatorDescription))
->identifier('nullsafe.neverNull')
Expand Down
23 changes: 11 additions & 12 deletions tests/PHPStan/Rules/Variables/NullCoalesceRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -253,22 +253,10 @@ public function testBug5933(): void
public function testBug7109(): void
{
$this->analyse([__DIR__ . '/../Properties/data/bug-7109.php'], [
[
'Using nullsafe property access "?->aaa" on left side of ?? is unnecessary. Use -> instead.',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no error with
https://3v4l.org/5TbIf#v8.3.30

so the ?-> seems useless.

17,
],
[
'Using nullsafe property access "?->aaa" on left side of ?? is unnecessary. Use -> instead.',
28,
],
[
'Expression on left side of ?? is not nullable.',
40,
],
[
'Using nullsafe property access "?->aaa" on left side of ?? is unnecessary. Use -> instead.',
66,
],
[
'Expression on left side of ?? is not nullable.',
73,
Expand Down Expand Up @@ -372,4 +360,15 @@ public function testBug13921(): void
]);
}

#[RequiresPhp('>= 8.0')]
public function testNullsafeCoalesceNullableObject(): void
{
$this->analyse([__DIR__ . '/data/bug-nullsafe-coalesce-nullable-object.php'], [
[
'Expression on left side of ?? is not nullable.',
59,
],
]);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php // lint >= 8.0

namespace BugNullsafeCoalesceNullableObject;

class Detail
{
public string $label;

public function __construct(string $label)
{
$this->label = $label;
}
}

class Node
{
private ?Detail $detail;

public function __construct(?Detail $detail)
{
$this->detail = $detail;
}

public function getDetail(): ?Detail
{
return $this->detail;
}
}

class Root
{
private ?Node $node;

public function __construct(?Node $node)
{
$this->node = $node;
}

public function getNode(): ?Node
{
return $this->node;
}
}

class Foo
{
public function chainedNullable(Root $root): void
{
$a = $root->getNode()?->getDetail()?->label ?? '';
}

public function singleNullable(Node $node): void
{
$a = $node->getDetail()?->label ?? '';
}

public function allNonNullable(Detail $detail): void
{
$a = $detail?->label ?? '';
}
}
Loading