Skip to content

fix(cycle-detection): drop type-spec analysis and add method-call support#191

Merged
notJoon merged 1 commit into
mainfrom
fix/cycle-detection-false-positive
May 5, 2026
Merged

fix(cycle-detection): drop type-spec analysis and add method-call support#191
notJoon merged 1 commit into
mainfrom
fix/cycle-detection-false-positive

Conversation

@notJoon

@notJoon notJoon commented May 5, 2026

Copy link
Copy Markdown
Member

Description

The cycle-detection rule used to walk every TypeSpec/ValueSpec identifier and emit "function call cycle" errors on mutually recursive struct types via pointer/slice indirection. Every legal Go recursive type goes through such indirection (direct embedding is a compile error), so the analysis only produced false positives.

Drop analyzeTypeSpec and analyzeValueSpec entirely. The rule now analyzes only function calls, matching the message it already emits.

Two latent gaps in the call-graph builder are fixed in the same change because dropping the type-spec edges without them would silently regress the rule's canonical use case:

  • analyzeFuncDecl filtered call-site idents to ident.Name == name, so mutual function recursion (a calls b calls a) was never recorded — only type-spec pollution surfaced those cycles.
  • Method calls are now resolved when the selector receiver matches the enclosing method's receiver param, so T.foo calling T.bar and back is detected. Cross-type calls and calls through variables still need go/types resolution and remain out of scope.

testdata/cycle/types.gno only existed to assert the now-deprecated type-cycle behavior and is removed; the engine integration test points at the existing testdata/cycle0.gno function-cycle fixture.

…port

The cycle-detection rule used to walk every TypeSpec/ValueSpec
identifier and emit "function call cycle" errors on mutually recursive
struct types via pointer/slice indirection. Every legal Go recursive
type goes through such indirection (direct embedding is a compile
error), so the analysis only produced false positives — most recently
breaking gno-ibc CI on a Schema/Field tree type.

Drop analyzeTypeSpec and analyzeValueSpec entirely. The rule now
analyzes only function calls, matching the message it already emits.

Two latent gaps in the call-graph builder are fixed in the same
change because dropping the type-spec edges without them would
silently regress the rule's canonical use case:

- analyzeFuncDecl filtered call-site idents to ident.Name == name,
  so mutual function recursion (a calls b calls a) was never
  recorded — only type-spec pollution surfaced those cycles.
- Method calls are now resolved when the selector receiver matches
  the enclosing method's receiver param, so T.foo calling T.bar and
  back is detected. Cross-type calls and calls through variables
  still need go/types resolution and remain out of scope.

Tests cover the gno-ibc Field/Schema reproducer plus a battery of
shapes that must not trigger (self-pointer linked list, recursive
map values, function-typed field, embedded mutual via pointers,
slice-of-pointer-to-self, pointer var initializers, type alias
chains) and positive same-type method recursion cases.

testdata/cycle/types.gno only existed to assert the now-deprecated
type-cycle behavior and is removed; the engine integration test
points at the existing testdata/cycle0.gno function-cycle fixture.
@notJoon notJoon merged commit 583a819 into main May 5, 2026
6 checks passed
@notJoon notJoon deleted the fix/cycle-detection-false-positive branch May 5, 2026 00:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant