From bdce35fd9cd4eb2518ca518122d753f1fade4597 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sun, 28 Feb 2021 14:32:46 +0200 Subject: [PATCH] parser: support `static x := 42` in [unsafe] functions too --- vlib/v/parser/assign.v | 6 +++--- vlib/v/parser/fn.v | 2 ++ vlib/v/parser/parser.v | 1 + vlib/v/tests/static_vars_test.v | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 vlib/v/tests/static_vars_test.v diff --git a/vlib/v/parser/assign.v b/vlib/v/parser/assign.v index 499e9702b5..f164f34931 100644 --- a/vlib/v/parser/assign.v +++ b/vlib/v/parser/assign.v @@ -141,8 +141,8 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme iv := lx.info as ast.IdentVar share = iv.share if iv.is_static { - if !p.pref.translated && !p.pref.is_fmt { - p.error_with_pos('static variables are supported only in -translated mode', + if !p.pref.translated && !p.pref.is_fmt && !p.inside_unsafe_fn { + p.error_with_pos('static variables are supported only in -translated mode or in [unsafe] fn', lx.pos) return ast.Stmt{} } @@ -154,7 +154,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme name: lx.name expr: if left.len == right.len { right[i] } else { ast.Expr{} } share: share - is_mut: lx.is_mut || p.inside_for + is_mut: lx.is_mut || p.inside_for || is_static pos: lx.pos } if p.pref.autofree { diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 2152f415b5..1b2fa2c000 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -361,7 +361,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl { body_start_pos := p.peek_tok.position() if p.tok.kind == .lcbr { p.inside_fn = true + p.inside_unsafe_fn = is_unsafe stmts = p.parse_block_no_scope(true) + p.inside_unsafe_fn = false p.inside_fn = false } if !no_body && are_args_type_only { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 709644f25f..950ee8732a 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -38,6 +38,7 @@ mut: inside_or_expr bool inside_for bool inside_fn bool // true even with implicit main + inside_unsafe_fn bool // true when in fn, marked with `[unsafe]` inside_str_interp bool or_is_handled bool // ignore `or` in this expression builtin_mod bool // are we in the `builtin` module? diff --git a/vlib/v/tests/static_vars_test.v b/vlib/v/tests/static_vars_test.v new file mode 100644 index 0000000000..b1320605a2 --- /dev/null +++ b/vlib/v/tests/static_vars_test.v @@ -0,0 +1,16 @@ +[unsafe] +fn foo() int { + static x := 42 + x++ + return x +} + +fn xfoo() int { + return unsafe { foo() } +} + +fn test_static_vars_work() { + assert xfoo() == 43 + assert xfoo() == 44 + assert xfoo() == 45 +}