Skip to content

Commit ef8950a

Browse files
authored
Merge pull request #4203 from nspcc-dev/fix-access-strct-fld
compiler: emit default values in make
2 parents fcc2a9a + 58dbe17 commit ef8950a

2 files changed

Lines changed: 101 additions & 2 deletions

File tree

pkg/compiler/codegen.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,8 +1986,18 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
19861986
if isByteSlice(typ) {
19871987
emit.Opcodes(c.prog.BinWriter, opcode.NEWBUFFER)
19881988
} else {
1989-
neoT := toNeoType(typ.(*types.Slice).Elem())
1990-
emit.Instruction(c.prog.BinWriter, opcode.NEWARRAYT, []byte{byte(neoT)})
1989+
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
1990+
start := c.newLabel()
1991+
c.setLabel(start)
1992+
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
1993+
end := c.newLabel()
1994+
emit.Jmp(c.prog.BinWriter, opcode.JMPIFNOTL, end)
1995+
emit.Opcodes(c.prog.BinWriter, opcode.DEC)
1996+
c.emitDefault(typ.(*types.Slice).Elem())
1997+
emit.Opcodes(c.prog.BinWriter, opcode.ROT, opcode.ROT)
1998+
emit.Jmp(c.prog.BinWriter, opcode.JMPL, start)
1999+
c.setLabel(end)
2000+
emit.Opcodes(c.prog.BinWriter, opcode.DROP, opcode.PACK)
19912001
}
19922002
}
19932003
case "len":

pkg/compiler/slice_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,95 @@ func TestMake(t *testing.T) {
636636
_, err := compiler.Compile("foo.go", strings.NewReader(src))
637637
require.Error(t, err)
638638
})
639+
t.Run("StructFieldInt", func(t *testing.T) {
640+
src := `package main
641+
642+
type nested struct{ t int }
643+
type test struct{ a []nested }
644+
645+
func Main() int {
646+
var myStruct = test{a: make([]nested, 1)}
647+
return myStruct.a[0].t
648+
}`
649+
eval(t, src, big.NewInt(0))
650+
})
651+
652+
t.Run("NestedStructField", func(t *testing.T) {
653+
src := `package main
654+
655+
type level2 struct{ v int }
656+
type level1 struct{ x level2 }
657+
type test struct{ a []level1 }
658+
659+
func Main() int {
660+
var myStruct = test{a: make([]level1, 1)}
661+
return myStruct.a[0].x.v
662+
}`
663+
eval(t, src, big.NewInt(0))
664+
})
665+
666+
t.Run("MultipleElementsAreZeroed", func(t *testing.T) {
667+
src := `package main
668+
669+
type nested struct{ t int }
670+
type test struct{ a []nested }
671+
672+
func Main() int {
673+
var myStruct = test{a: make([]nested, 3)}
674+
return myStruct.a[0].t + myStruct.a[1].t + myStruct.a[2].t
675+
}`
676+
eval(t, src, big.NewInt(0))
677+
})
678+
679+
t.Run("SliceFieldIsNilButReadable", func(t *testing.T) {
680+
src := `package main
681+
682+
type nested struct{ items []int }
683+
type test struct{ a []nested }
684+
685+
func Main() int {
686+
var myStruct = test{a: make([]nested, 1)}
687+
return len(myStruct.a[0].items)
688+
}`
689+
eval(t, src, big.NewInt(0))
690+
})
691+
692+
t.Run("BoolAndStringZeroValues", func(t *testing.T) {
693+
src := `package main
694+
695+
type nested struct{
696+
ok bool
697+
s string
698+
}
699+
type test struct{ a []nested }
700+
701+
func Main() int {
702+
var myStruct = test{a: make([]nested, 1)}
703+
if myStruct.a[0].ok {
704+
return 1
705+
}
706+
if myStruct.a[0].s != "" {
707+
return 2
708+
}
709+
return 0
710+
}`
711+
eval(t, src, big.NewInt(0))
712+
})
713+
714+
t.Run("DeeplyNestedStruct", func(t *testing.T) {
715+
src := `package main
716+
717+
type leaf struct{ n int }
718+
type mid struct{ l leaf }
719+
type root struct{ m mid }
720+
type test struct{ a []root }
721+
722+
func Main() int {
723+
var myStruct = test{a: make([]root, 1)}
724+
return myStruct.a[0].m.l.n
725+
}`
726+
eval(t, src, big.NewInt(0))
727+
})
639728
}
640729

641730
func TestCopy(t *testing.T) {

0 commit comments

Comments
 (0)