Skip to content

Commit ee85996

Browse files
authored
Fix to handling of case null (#1235)
1 parent d655f8f commit ee85996

2 files changed

Lines changed: 38 additions & 4 deletions

File tree

jdk-recent-unit-tests/src/test/java/com/uber/nullaway/jdk17/SwitchTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,29 @@ public void switchStatementCaseNull() {
268268
.doTest();
269269
}
270270

271+
@Test
272+
public void caseNullTypeRefinement() {
273+
defaultCompilationHelper
274+
.addSourceLines(
275+
"TestCase.java",
276+
"import java.io.IOException;",
277+
"import org.jspecify.annotations.NullMarked;",
278+
"@NullMarked",
279+
"public class TestCase {",
280+
" boolean hasRelevantMessage(IOException ioException)",
281+
" {",
282+
" String message = ioException.getMessage();",
283+
" return switch (message)",
284+
" {",
285+
" case null -> false;",
286+
" case \"Operation timed out\", \"Connection reset by peer\", \"Premature EOF\", \"Error writing to server\" -> true;",
287+
" default -> message.contains(\"GOAWAY received\");",
288+
" };",
289+
" }",
290+
"}")
291+
.doTest();
292+
}
293+
271294
@Test
272295
public void issue1168() {
273296
defaultCompilationHelper

nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessPropagation.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,21 +411,23 @@ public TransferResult<Nullness, NullnessStore> visitGreaterThanOrEqual(
411411
public TransferResult<Nullness, NullnessStore> visitEqualTo(
412412
EqualToNode equalToNode, TransferInput<Nullness, NullnessStore> input) {
413413
return handleEqualityComparison(
414-
input, equalToNode.getLeftOperand(), equalToNode.getRightOperand(), true);
414+
input, equalToNode.getLeftOperand(), null, equalToNode.getRightOperand(), true);
415415
}
416416

417417
@Override
418418
public TransferResult<Nullness, NullnessStore> visitNotEqual(
419419
NotEqualNode notEqualNode, TransferInput<Nullness, NullnessStore> input) {
420420
return handleEqualityComparison(
421-
input, notEqualNode.getLeftOperand(), notEqualNode.getRightOperand(), false);
421+
input, notEqualNode.getLeftOperand(), null, notEqualNode.getRightOperand(), false);
422422
}
423423

424424
/**
425425
* Handle nullability refinements from an equality comparison.
426426
*
427427
* @param input transfer input for the operation
428428
* @param leftOperand left operand of the comparison
429+
* @param leftOperandNullness nullness of left operand if it is not a sub node of {@code
430+
* input.getNode()}, {@code null} otherwise
429431
* @param rightOperand right operand of the comparison
430432
* @param equalTo if {@code true}, the comparison is an equality comparison, otherwise it is a
431433
* dis-equality ({@code !=}) comparison
@@ -434,12 +436,14 @@ public TransferResult<Nullness, NullnessStore> visitNotEqual(
434436
private TransferResult<Nullness, NullnessStore> handleEqualityComparison(
435437
TransferInput<Nullness, NullnessStore> input,
436438
Node leftOperand,
439+
@Nullable Nullness leftOperandNullness,
437440
Node rightOperand,
438441
boolean equalTo) {
439442
ReadableUpdates thenUpdates = new ReadableUpdates();
440443
ReadableUpdates elseUpdates = new ReadableUpdates();
441444
SubNodeValues inputs = values(input);
442-
Nullness leftVal = inputs.valueOfSubNode(leftOperand);
445+
Nullness leftVal =
446+
leftOperandNullness != null ? leftOperandNullness : inputs.valueOfSubNode(leftOperand);
443447
Nullness rightVal = inputs.valueOfSubNode(rightOperand);
444448
Nullness equalBranchValue = leftVal.greatestLowerBound(rightVal);
445449
Updates equalBranchUpdates = equalTo ? thenUpdates : elseUpdates;
@@ -965,7 +969,14 @@ public TransferResult<Nullness, NullnessStore> visitCase(
965969
// between the switch expression and the case operand.
966970
Node switchOperand = caseNode.getSwitchOperand().getExpression();
967971
Node caseOperand = caseOperands.get(0);
968-
return handleEqualityComparison(input, switchOperand, caseOperand, true);
972+
AccessPath switchOperandAccessPath =
973+
AccessPath.getAccessPathForNode(switchOperand, state, apContext);
974+
Nullness switchOperandNullness =
975+
switchOperandAccessPath == null
976+
? null
977+
: input.getRegularStore().getNullnessOfAccessPath(switchOperandAccessPath);
978+
return handleEqualityComparison(
979+
input, switchOperand, switchOperandNullness, caseOperand, true);
969980
}
970981
}
971982

0 commit comments

Comments
 (0)