Skip to content

fix(gnovm): depth-based shadowing for promoted struct fields and methods#5820

Draft
omarsy wants to merge 2 commits into
gnolang:masterfrom
omarsy:fix-method-shadowing
Draft

fix(gnovm): depth-based shadowing for promoted struct fields and methods#5820
omarsy wants to merge 2 commits into
gnolang:masterfrom
omarsy:fix-method-shadowing

Conversation

@omarsy

@omarsy omarsy commented Jun 12, 2026

Copy link
Copy Markdown
Member

Description

StructType.FindEmbeddedFieldType treated any second embedded match as a conflict, with no notion of promotion depth. So a method or field promoted from a shallower embedded field did not shadow a same-named one reachable deeper, and gno reported a spurious conflict and rejected valid programs:

type Deep struct{};    func (Deep) M() {}
type Mid struct{ Deep }              // M at depth 2
type Shallow struct{}; func (Shallow) M() {}
type T struct { Shallow; Mid }       // Go: T.M resolves to Shallow.M

gno rejected var i I = T{} at preprocess with T does not implement I (missing method M). On-chain addpkg type-checks with go/types first (which accepts these), so such a package passed the deployment gate and then panicked at VM preprocess.

Change

Search direct (depth-0) fields first (a direct field shadows promotion), then keep the shallowest embedded candidate (trail length = depth); two at the same shallowest depth are ambiguous. The recursion-guard set and the 5-value return contract are unchanged, so runtime selector navigation and all callers are unaffected.

Scope (important)

This closes the common disjoint-subtree shadowing case. It is a minimal, zero-regression step (verified by differential fuzzing vs. the Go toolchain: 0 regressions over 400 random shapes). It does not fix the broader pre-existing promotion bug where the shared recursion-guard set prunes legitimate paths when the same type is reachable via multiple embedded paths — tracked in #5819, which also covers the diamond false-accept. The ADR documents both out-of-scope cases.

Tests

embed_method_shadow0/1/2 pin the fix (they panic at preprocess on the old code); embed_method_shadow_ambiguous, embed_method_shadow_fieldmethod, and embed_method_shadow_internal_ambiguous are parity/regression guards (pass on old + new), with go/types parity via TypeCheckError directives. Confirmed against the Go toolchain across shadowing, multi-level, pointer-embedding, same-depth ambiguity, internally-ambiguous siblings, self-cycle, and embedded-interface cases.

Note

Draft. Local full-TestFiles suite passes (0 failures); CI will also run it. This PR is AI-assisted; ADR included per AGENTS.md (gnovm/adr/prxxxx_embedded_method_depth_shadowing.md, to be renamed with the PR number).

Related spec-compliance fixes from the same effort: #5784, #5785, #5807, #5808.

🤖 Generated with Claude Code

StructType.FindEmbeddedFieldType treated any second embedded match as a
conflict, with no notion of promotion depth. A method or field promoted
from a shallower embedded field therefore did NOT shadow a same-named one
reachable deeper, so gno reported a spurious conflict and rejected valid
programs:

  type Deep struct{};    func (Deep) M() {}
  type Mid struct{ Deep }              // M at depth 2
  type Shallow struct{}; func (Shallow) M() {}
  type T struct { Shallow; Mid }       // Go: T.M resolves to Shallow.M

gno rejected `var i I = T{}` at preprocess with "T does not implement I
(missing method M)". On-chain addpkg type-checks with go/types first
(which accepts these), so such a package passed the deployment gate and
then panicked at VM preprocess.

Search direct fields first (a depth-0 field shadows promotion), then keep
the shallowest embedded candidate (trail length = depth); two at the same
shallowest depth are ambiguous. The recursion-guard set and the return
contract are unchanged, so runtime selector navigation is unaffected.

Diamond ambiguity (the same embedded type reached via two paths at equal
depth) remains accepted as on upstream; it is gated on-chain by go/types
and is left as a follow-up (see ADR). Confirmed against the Go toolchain
across shadowing, multi-level, pointer-embedding, same-depth ambiguity,
internally-ambiguous siblings, self-cycle, and embedded-interface cases.
@Gno2D2

Gno2D2 commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

🛠 PR Checks Summary

All Automated Checks passed. ✅

Manual Checks (for Reviewers):
  • IGNORE the bot requirements for this PR (force green CI check)
Read More

🤖 This bot helps streamline PR reviews by verifying automated checks and providing guidance for contributors and reviewers.

✅ Automated Checks (for Contributors):

🟢 Maintainers must be able to edit this pull request (more info)
🟢 Pending initial approval by a review team member, or review from tech-staff

☑️ Contributor Actions:
  1. Fix any issues flagged by automated checks.
  2. Follow the Contributor Checklist to ensure your PR is ready for review.
    • Add new tests, or document why they are unnecessary.
    • Provide clear examples/screenshots, if necessary.
    • Update documentation, if required.
    • Ensure no breaking changes, or include BREAKING CHANGE notes.
    • Link related issues/PRs, where applicable.
☑️ Reviewer Actions:
  1. Complete manual checks for the PR, including the guidelines and additional checks if applicable.
📚 Resources:
Debug
Automated Checks
Maintainers must be able to edit this pull request (more info)

If

🟢 Condition met
└── 🟢 And
    ├── 🟢 The base branch matches this pattern: ^master$
    └── 🟢 The pull request was created from a fork (head branch repo: omarsy/gno)

Then

🟢 Requirement satisfied
└── 🟢 Maintainer can modify this pull request

Pending initial approval by a review team member, or review from tech-staff

If

🟢 Condition met
└── 🟢 And
    ├── 🟢 The base branch matches this pattern: ^master$
    └── 🟢 Not (🔴 Pull request author is a member of the team: tech-staff)

Then

🟢 Requirement satisfied
└── 🟢 If
    ├── 🟢 Condition
    │   └── 🟢 Or
    │       ├── 🔴 At least one of these user(s) reviewed the pull request: [aronpark1007 davd-gzl jefft0 notJoon omarsy MikaelVallenet] (with state "APPROVED")
    │       ├── 🔴 At least 1 user(s) of the team tech-staff reviewed pull request
    │       └── 🟢 This pull request is a draft
    └── 🟢 Then
        └── 🟢 Not (🔴 This label is applied to pull request: review/triage-pending)

Manual Checks
**IGNORE** the bot requirements for this PR (force green CI check)

If

🟢 Condition met
└── 🟢 On every pull request

Can be checked by

  • Any user with comment edit permission

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📦 🤖 gnovm Issues or PRs gnovm related

Projects

Development

Successfully merging this pull request may close these issues.

2 participants