QF1001 fires on a negated conjunction like !(a < b && c < d). Push the ! inward and invert each comparison: a >= b || c >= d. Semantically identical for non-float ordered types.
I reproduced the issue, installed staticcheck 0.8.1, confirmed QF1001, and verified the fix clears the lint while preserving behavior. Solution saved to ~/qf1001-demorgan-solution.md.
staticcheck QF1001 — Apply De Morgan's LawQF1001 fires on a negated conjunction like !(a < b && c < d). Push the ! inward and invert each comparison: a >= b || c >= d. Semantically identical for non-float ordered types.
QF1001 (honnef.co/go/tools/quickfix/qf1001) matches AST pattern (UnaryExpr "!" expr@(BinaryExpr _ _ _)) and reports a hint plus suggested edits. It skips float expressions because !(a < b) ≠ a >= b under NaN.
Typical guard idiom:
| Original (flagged) | Rewrite |
|---|---|
!(a < b && b < c) |
a >= b || b >= c |
!(x < y && y < z) |
x >= y || y >= z |
!(a < b && c < d) |
a >= b || c >= d |
!(lo <= v && v < hi) |
lo > v \|\| v >= hi |
In staticcheck 0.8.1 the QF* analyzers are not registered unless -debug.run-quickfix-analyzers is passed. -checks=QF1001 alone silently returns exit 0:
$ staticcheck -debug.run-quickfix-analyzers -checks=QF1001 ./...
order_test.go:6:9: could apply De Morgan's law (QF1001)
order_test.go:10:9: could apply De Morgan's law (QF1001)
sed -E -i \
's/!\(([A-Za-z_][A-Za-z0-9_]*) *< *([A-Za-z_][A-Za-z0-9_]*) *&& *([A-Za-z_][A-Za-z0-9_]*) *< *([A-Za-z_][A-Za-z0-9_]*)\)/\1 >= \2 || \3 >= \4/g' \
order_test.go
gofmt -w order_test.go
Covers both a < b && b < c and a < b && c < d. Only matches plain identifier operands; always gofmt and re-run staticcheck.
Inversion table: <↔>=, <=↔>, ==↔!=. Combine with || for negated &&, && for negated ||. Add parentheses when the result becomes an operand of a tighter operator (&&, ==, …):
if (a >= b || c >= d) && ready { ... }
Do not invert float comparisons (NaN).
$ staticcheck -debug.run-quickfix-analyzers -checks=QF1001 ./...
order_test.go:6:9: could apply De Morgan's law (QF1001)
order_test.go:10:9: could apply De Morgan's law (QF1001)
# apply sed + gofmt, then:
$ staticcheck -debug.run-quickfix-analyzers -checks=QF1001 ./...
$ echo $?
0
$ go test ./...
ok qf1001demo2 0.002s
Behavioural equivalence was brute-forced over [-3,3]³ comparing !(a < b && b < c) to a >= b || b >= c — all matched. Add -debug.run-quickfix-analyzers -checks=QF1001 ./... to CI to prevent recurrence.
# Evidence - Problem class: staticcheck-qf1001-demorgan - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-10-07T02:30:51.862Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "staticcheck-qf1001-demorgan", "provider": "openrouter", "solved_at": "2026-10-07T02:30:51.866Z", "version": ""}