cl: preserve required nil dereference checks - #2256
Conversation
There was a problem hiding this comment.
Review: preserve nil checks for unused dereferences
The core change is correct and well-tested: collapsing the large-value / slice-conversion special cases into a single unconditional guard path ensures _ = *p still panics on a nil pointer, and the added compiler-IR and runtime regression tests (TestUnusedDerefEmitsNilGuard, TestUnusedNilDerefOperationsPanic) lock in the behavior. The retained skipUnusedArrayDeref carve-out is a correct, spec-mandated exception (ranging over / len of a *[N]T must not dereference the pointer). No correctness, security, or documentation-accuracy issues were found — the removed CHECK lines in cvar/varinit and the two dropped issue38496.go xfails are consistent with the new behavior.
Two non-blocking quality/performance findings are noted inline. Both concern emitting nil guards that are provably dead in specific cases; neither affects correctness.
Optional follow-up: test coverage for the collapsed branches
The new tests cover a small direct pointer and an array-element load, but not the two cases whose dedicated handling was removed — an unused deref of a large non-pointer struct, and an unused zero-length slice-to-array-conversion deref. Adding those would lock in the merged branch's behavior for exactly the paths that were deleted.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
LLGo baseline benchmarks
Program measurements
Core language and compiler benchmarks
No main baseline exists yet; all metrics are marked Warning
|
|
Handled both review findings in
Fresh validation passes: focused compiler/fixture tests, the LLGo runtime nil-deref regression, and upstream |
50c5332 to
3220195
Compare
|
Expanded and rebased this PR in
Direct nil pointer receivers remain legal and are covered by a control test. The final implementation also removes redundant checks on already-derived addresses. Fresh validation passes for the focused compiler suite, all new LLGo runtime cases, all affected LLVM snapshots, and upstream |
|
The first CI run exposed a conservative-GC interaction rather than a nil-check correctness failure: both Ubuntu LLGo matrix jobs failed the ESP32-C3 Fixed in
Fresh local validation passes: full |
|
The prior branch-only change fixed
With the exact Espressif QEMU setup used by CI, the complete |
|
Addressed the patch-coverage failure in |
|
Added focused fail-closed coverage in The previous Codecov report had 61 missed/partial lines in the new |
|
Codecov has now processed |
Summary
FieldAddrandIndexAddrchains back to the actual pointer base, including indexed address-of selectorsfixedbugs/issue38496.goandnilptr2.goThe implementation does not special-case either upstream test. These cases share one root cause: the effective load address may be non-nil, or the load may disappear entirely, even though evaluating the original Go expression must still panic at its nil pointer base.
The local non-nil proof deliberately stops at calls, unknown aliases, nil overwrites, joins, and loops. This is also required for the conservative ESP32-C3 collector: unnecessary pointer checks can otherwise spill already-dead pointers and retain objects, while removing a check without a valid memory fact would break Go nil-panic behavior.
The branch is based on current xgo-dev
main(60c30f2ff). This PR does not change CI configuration or timing.Validation
== nil/!= nilformstprecurfn, passes; affected testdata/testgo/testrt cases pass with unchanged Go source bodiesnilptr2.goandfixedbugs/issue38496.gopass on Go 1.26.5; the nil group also previously passed on Go 1.24.11 and 1.25.7gc-runtimesuite passes under the same Espressif QEMU used by CI, includingInterfaceLiveness,NestedStructPointers, andMultipleCyclesDisjointcltests andgit diff --checkpass