Error Prone version
Error Prone 2.49.0 (javac plugin) — javac 21.0.8, source/target 21.
Check name
LoopConditionChecker
Description
LoopConditionChecker flags loops whose condition variable(s) are never modified in the loop body (a no-op or infinite loop). The check is sensitive to the syntactic form of the loop bound rather than its compile-time-constant value: replacing the literal 1 with a static final int ONE = 1 — which javac inlines as the constant 1 — silences the diagnostic, even though the loop is byte-for-byte identical at runtime and is still an infinite loop.
Reproducer
// BEFORE — LoopConditionChecker fires on the second loop
class C {
void foo() {
for (int i = 0; i < 1; i++) {} // i is modified -> not flagged
for (int i = 0; i < 1; foo()) {} // i never modified -> FLAGGED
}
}
// AFTER — semantically identical (ONE is the constant 1), rule no longer fires
class C { static final int ONE = 1;
void foo() {
for (int i = 0; i < ONE; i++) {}
for (int i = 0; i < ONE; foo()) {} // still an infinite loop, NOT flagged
}
}
Expected behavior
LoopConditionChecker should report the same finding on BEFORE and AFTER. ONE is a compile-time constant equal to 1, so i < ONE and i < 1 are identical, and the second loop is an infinite loop in both forms.
Actual behavior
- BEFORE: 1 finding —
condition variable(s) never modified in loop body: i on the for (int i = 0; i < 1; foo()) loop.
- AFTER: 0 findings. The checker bails out once the bound is a named constant instead of a literal, failing to constant-fold the condition operand.
Error Prone version
Error Prone 2.49.0 (javac plugin) — javac 21.0.8, source/target 21.
Check name
LoopConditionChecker
Description
LoopConditionCheckerflags loops whose condition variable(s) are never modified in the loop body (a no-op or infinite loop). The check is sensitive to the syntactic form of the loop bound rather than its compile-time-constant value: replacing the literal1with astatic final int ONE = 1— which javac inlines as the constant1— silences the diagnostic, even though the loop is byte-for-byte identical at runtime and is still an infinite loop.Reproducer
Expected behavior
LoopConditionCheckershould report the same finding on BEFORE and AFTER.ONEis a compile-time constant equal to1, soi < ONEandi < 1are identical, and the second loop is an infinite loop in both forms.Actual behavior
condition variable(s) never modified in loop body: ion thefor (int i = 0; i < 1; foo())loop.