zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 298abbcff86629273f24891d243fb6e503392e8f (tree)
parent fb05b96492f4fb1476106bf735788ac16f69c7ef
Author: kristopher tate <kt@connectfree.co.jp>
Date:   Fri,  3 Aug 2018 02:55:31 +0900

better support for `_` identifier

 * disallow variable declaration of `_`
 * prevent `_` from shadowing itself
 * prevent read access of `_`

closes #1204
closes #1320

Diffstat:
Msrc/ir.cpp | 16+++++++++++++++-
Mtest/behavior.zig | 1+
Atest/cases/underscore.zig | 28++++++++++++++++++++++++++++
Mtest/compile_errors.zig | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 102 insertions(+), 1 deletion(-)

diff --git a/src/ir.cpp b/src/ir.cpp @@ -3332,7 +3332,15 @@ static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Sco static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime) { - VariableTableEntry *var = create_local_var(irb->codegen, node, scope, name, src_is_const, gen_is_const, is_shadowable, is_comptime); + bool is_underscored = name ? buf_eql_str(name, "_") : false; + VariableTableEntry *var = create_local_var( irb->codegen + , node + , scope + , (is_underscored ? nullptr : name) + , src_is_const + , gen_is_const + , (is_underscored ? true : is_shadowable) + , is_comptime ); if (is_comptime != nullptr || gen_is_const) { var->mem_slot_index = exec_next_mem_slot(irb->exec); var->owner_exec = irb->exec; @@ -5186,6 +5194,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; + if (buf_eql_str(variable_declaration->symbol, "_")) { + add_node_error(irb->codegen, node, buf_sprintf("`_` is not a declarable symbol")); + return irb->codegen->invalid_instruction; + } + IrInstruction *type_instruction; if (variable_declaration->type != nullptr) { type_instruction = ir_gen_node(irb, variable_declaration->type, scope); @@ -5198,6 +5211,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod bool is_shadowable = false; bool is_const = variable_declaration->is_const; bool is_extern = variable_declaration->is_extern; + IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime); VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol, diff --git a/test/behavior.zig b/test/behavior.zig @@ -60,6 +60,7 @@ comptime { _ = @import("cases/try.zig"); _ = @import("cases/type_info.zig"); _ = @import("cases/undefined.zig"); + _ = @import("cases/underscore.zig"); _ = @import("cases/union.zig"); _ = @import("cases/var_args.zig"); _ = @import("cases/void.zig"); diff --git a/test/cases/underscore.zig b/test/cases/underscore.zig @@ -0,0 +1,28 @@ +const std = @import("std"); +const assert = std.debug.assert; + +test "ignore lval with underscore" { + _ = false; +} + +test "ignore lval with underscore (for loop)" { + for ([]void{}) |_, i| { + for ([]void{}) |_, j| { + break; + } + break; + } +} + +test "ignore lval with underscore (while loop)" { + while (optionalReturnError()) |_| { + while (optionalReturnError()) |_| { + break; + } else |_| { } + break; + } else |_| { } +} + +fn optionalReturnError() !?u32 { + return error.optionalReturnError; +} diff --git a/test/compile_errors.zig b/test/compile_errors.zig @@ -23,6 +23,64 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ); cases.add( + "`_` is not a declarable symbol", + \\export fn f1() usize { + \\ var _: usize = 2; + \\ return _; + \\} + , + ".tmp_source.zig:2:5: error: `_` is not a declarable symbol", + ".tmp_source.zig:3:12: error: use of undeclared identifier '_'", + ); + + cases.add( + "`_` should not be usable inside for", + \\export fn returns() void { + \\ for ([]void{}) |_, i| { + \\ for ([]void{}) |_, j| { + \\ return _; + \\ } + \\ } + \\} + , + ".tmp_source.zig:4:20: error: use of undeclared identifier '_'", + ); + + cases.add( + "`_` should not be usable inside while", + \\export fn returns() void { + \\ while (optionalReturn()) |_| { + \\ while (optionalReturn()) |_| { + \\ return _; + \\ } + \\ } + \\} + \\fn optionalReturn() ?u32 { + \\ return 1; + \\} + , + ".tmp_source.zig:4:20: error: use of undeclared identifier '_'", + ); + + cases.add( + "`_` should not be usable inside while else", + \\export fn returns() void { + \\ while (optionalReturnError()) |_| { + \\ while (optionalReturnError()) |_| { + \\ return; + \\ } else |_| { + \\ if (_ == error.optionalReturnError) return; + \\ } + \\ } + \\} + \\fn optionalReturnError() !?u32 { + \\ return error.optionalReturnError; + \\} + , + ".tmp_source.zig:6:17: error: use of undeclared identifier '_'", + ); + + cases.add( "while loop body expression ignored", \\fn returns() usize { \\ return 2;