fix(gnovm): allow type-switch with sole case nil: (preprocess single-case branch must tag-type-only when ct is nil) - #5766
Conversation
…e-case branch must tag-type-only when ct is nil)
🛠 PR Checks SummaryAll Automated Checks passed. ✅ Manual Checks (for Reviewers):
Read More🤖 This bot helps streamline PR reviews by verifying automated checks and providing guidance for contributors and reviewers. ✅ Automated Checks (for Contributors):No automated checks match this pull request. ☑️ Contributor Actions:
☑️ Reviewer Actions:
📚 Resources:Debug
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Reserve() remains the legitimate entry point for nil-typed placeholder slots; Define() is for real bindings only. Catches the type-switch `case nil:` class of bug at the offending caller instead of as a confusing downstream "name not declared" panic.
There was a problem hiding this comment.
The change look good. I left a minor suggestion; please take a look and feel free to apply them.
not necessary, but I think it would be good to have a test that distinguishes between an interface containing a nil value and one with no dynamic type at all.
for example:
// PATH: gnovm/tests/files/typeswitch2.gno
package main
type S struct{}
func classify(x any) {
switch v := x.(type) {
case nil:
println("nil", v == nil)
case *S:
println("*S", v == nil)
default:
panic("unexpected type")
}
}
func main() {
classify(nil)
classify((*S)(nil))
classify(&S{})
}
// Output:
// nil true
// *S true
// *S falsehttps://go.dev/play/p/hOcVkHTayGI
nil has no dynamic type, so it enters case nil. In contrast, (*S)(nil) still has the dynamic type *S even though the underlying pointer value is nil, so it enters case *S. and I confirmed that this passes on my side.
Since this change adds support for case nil, testing this boundary as well would help ensure the behavior is robust and the intent is clear.
Co-authored-by: Lee ByeongJun <lbj199874@gmail.com>
Co-authored-by: Lee ByeongJun <lbj199874@gmail.com>
Co-authored-by: Lee ByeongJun <lbj199874@gmail.com>
… in type switch Suggested in review: #5766 (review)
case nil:(e.g.switch xx := x.(type) { case nil: ... }) panicked at preprocess withname xx not declaredbecause the single-case shortcut registered the switch var withanyValue(ct)wherect == nil; after: the sole-nilform is accepted andxxis bound to the tag's static type, matching Go.preprocess1's*TypeSwitchStmtbranch ingnovm/pkg/gnolang/preprocess.gonow gates thelen(n.Cases) == 1define-with-case-type shortcut onct != nil, so a nilctfalls through to the same tag-type define used for multi-case switches.gnovm/tests/files/typeswitch1.gnomirrors gocorpus's typeswitch1 (solecase nil:alongside mixed multi-type cases) and exercises both thexx := x.(type)and barexx.(type)shapes.