Skip to content

[DeadCode] Add RemoveRedundantTypeCheckRector - #8307

Merged
TomasVotruba merged 4 commits into
mainfrom
remove-redundant-nullable-type-check
Aug 6, 2026
Merged

[DeadCode] Add RemoveRedundantTypeCheckRector#8307
TomasVotruba merged 4 commits into
mainfrom
remove-redundant-nullable-type-check

Conversation

@TomasVotruba

@TomasVotruba TomasVotruba commented Aug 6, 2026

Copy link
Copy Markdown
Member

Removes is_<type>() check that can never fail, because the type is already known.

Two shapes are handled.

1) null === compare + negated type check - real-world case on getSecurity(): ?string

 $securityExpression = $operation->getSecurity();
-if (null === $securityExpression || ! is_string($securityExpression)) {
+if (null === $securityExpression) {
     return;
 }

Once null is excluded, is_string() on a ?string is always true, so the negated check is dead. The condition narrows to the first one.

2) truthy check + type check

 public function buildWhereClauseFromArray($query, array $clauses, $expr = null)
 {
-    if ($clauses && is_array($clauses)) {
+    if ($clauses) {

$clauses is typed array, so is_array() can never fail.

Handles is_string, is_int/is_integer/is_long, is_float/is_double, is_bool, is_array, is_object.

Skipped:

// wider union - is_string() can still fail on int
if (null === $value || ! is_string($value)) {
}

// wider union - is_array() can still fail on string
if ($value && is_array($value)) {
}

// untyped param
public function run($value)
{
    if (null === $value || ! is_string($value)) {
    }
}

// different variable
if (null === $value || ! is_string($anotherValue)) {
}

Registered in DeadCodeLevel.

Includes #8308 as its first commit, as CI on main is currently red on a stray fixture file; the diff shrinks once that is merged.

@TomasVotruba
TomasVotruba force-pushed the remove-redundant-nullable-type-check branch from 99190b5 to ba03075 Compare August 6, 2026 09:44
@TomasVotruba TomasVotruba changed the title [DeadCode] Add RemoveRedundantNullableTypeCheckRector [DeadCode] Add RemoveRedundantTypeCheckRector Aug 6, 2026
return null;
}

$comparedType = $this->getType($nullComparedExpr);

@samsonasik samsonasik Aug 6, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should use getNativeType(), ensure type via @param docblock skipped, eg:

/**
 * @param ?string $p
 */
function p($p) {

}

Also, there is ExprAnalyzer::isNonTypedFromParam() check for it

public function isNonTypedFromParam(Expr $expr): bool

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch, switched both branches to getNativeType() and added the ExprAnalyzer::isNonTypedFromParam() bail-out. Two skip fixtures cover it:

/**
 * @param ?string $value
 */
public function run($value): void
{
    if (null === $value || ! is_string($value)) {
        return;
    }
}

/**
 * @param mixed[] $clauses
 */
public function run($clauses): void
{
    if ($clauses && is_array($clauses)) {
        return;
    }
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch, thank you 👍

@TomasVotruba
TomasVotruba merged commit 85d180e into main Aug 6, 2026
64 checks passed
@TomasVotruba
TomasVotruba deleted the remove-redundant-nullable-type-check branch August 6, 2026 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants