diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 40600ead69d..cf218f7a5d5 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1295,6 +1295,17 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { n.Path = NewValuePathBlock(0, 0, blankIdentifier) return n, TRANS_CONTINUE case "iota": + // iota is a non-shadowable builtin; reject declaring a new + // identifier named "iota" (`iota := 5` or `for iota := range x`) + // instead of falling through to the constant-only check below. + isDefine := ftype == TRANS_RANGE_KEY || ftype == TRANS_RANGE_VALUE + if as, ok := ns[len(ns)-1].(*AssignStmt); ok { + isDefine = isDefine || (ftype == TRANS_ASSIGN_LHS && as.Op == DEFINE) + } + if isDefine { + panic(fmt.Sprintf("builtin identifiers cannot be shadowed: %s", n.Name)) + } + pd := lastDecl(ns) valueDecl, ok := pd.(*ValueDecl) if !ok || !valueDecl.Const { diff --git a/gnovm/tests/files/iota_identifier.gno b/gnovm/tests/files/iota_identifier.gno new file mode 100644 index 00000000000..87855f15fea --- /dev/null +++ b/gnovm/tests/files/iota_identifier.gno @@ -0,0 +1,9 @@ +package main + +func main() { + iota := 5 // ERROR "builtin identifiers cannot be shadowed" + _ = iota +} + +// Error: +// main/iota_identifier.gno:4:2-6: builtin identifiers cannot be shadowed: iota diff --git a/gnovm/tests/files/iota_identifier_range.gno b/gnovm/tests/files/iota_identifier_range.gno new file mode 100644 index 00000000000..b1d70dfc6bb --- /dev/null +++ b/gnovm/tests/files/iota_identifier_range.gno @@ -0,0 +1,11 @@ +package main + +func main() { + s := []int{1, 2, 3} + for iota := range s { // ERROR "builtin identifiers cannot be shadowed" + _ = iota + } +} + +// Error: +// main/iota_identifier_range.gno:5:6-10: builtin identifiers cannot be shadowed: iota