diff --git a/src/AstGen.zig b/src/AstGen.zig index fcf5835f1e..06557f900b 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -6312,6 +6312,9 @@ fn switchExpr( }, ); } + if (case.inline_token != null) { + return astgen.failTok(case_src, "cannot inline '_' prong", .{}); + } special_node = case_node; special_prong = .under; underscore_src = case_src; @@ -6365,8 +6368,8 @@ fn switchExpr( var scalar_case_index: u32 = 0; for (case_nodes) |case_node| { const case = switch (node_tags[case_node]) { - .switch_case_one => tree.switchCaseOne(case_node), - .switch_case => tree.switchCase(case_node), + .switch_case_one, .switch_case_inline_one => tree.switchCaseOne(case_node), + .switch_case, .switch_case_inline => tree.switchCase(case_node), else => unreachable, }; @@ -6506,7 +6509,8 @@ fn switchExpr( const case_slice = case_scope.instructionsSlice(); const body_len = astgen.countBodyLenAfterFixups(case_slice); try payloads.ensureUnusedCapacity(gpa, body_len); - payloads.items[body_len_index] = body_len; + const inline_bit = @as(u32, @boolToInt(case.inline_token != null)) << 31; + payloads.items[body_len_index] = body_len | inline_bit; appendBodyWithFixupsArrayList(astgen, payloads, case_slice); } } @@ -6553,7 +6557,7 @@ fn switchExpr( end_index += 3 + items_len + 2 * ranges_len; } - const body_len = payloads.items[body_len_index]; + const body_len = @truncate(u31, payloads.items[body_len_index]); end_index += body_len; switch (strat.tag) { @@ -9134,7 +9138,9 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { .@"usingnamespace", .test_decl, .switch_case, + .switch_case_inline, .switch_case_one, + .switch_case_inline_one, .container_field_init, .container_field_align, .container_field, diff --git a/src/Sema.zig b/src/Sema.zig index f6a84341cc..cf7a2a3036 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9237,7 +9237,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const special: struct { body: []const Zir.Inst.Index, end: usize } = switch (special_prong) { .none => .{ .body = &.{}, .end = header_extra_index }, .under, .@"else" => blk: { - const body_len = sema.code.extra[header_extra_index]; + const body_len = @truncate(u31, sema.code.extra[header_extra_index]); const extra_body_start = header_extra_index + 1; break :blk .{ .body = sema.code.extra[extra_body_start..][0..body_len], @@ -9307,7 +9307,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError while (scalar_i < scalar_cases_len) : (scalar_i += 1) { const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; extra_index += body_len; @@ -9328,7 +9328,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError extra_index += 1; const ranges_len = sema.code.extra[extra_index]; extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; const items = sema.code.refSlice(extra_index, items_len); extra_index += items_len + body_len; @@ -9407,7 +9407,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError while (scalar_i < scalar_cases_len) : (scalar_i += 1) { const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; extra_index += body_len; @@ -9427,7 +9427,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError extra_index += 1; const ranges_len = sema.code.extra[extra_index]; extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; const items = sema.code.refSlice(extra_index, items_len); extra_index += items_len + body_len; @@ -9549,7 +9549,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError while (scalar_i < scalar_cases_len) : (scalar_i += 1) { const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; extra_index += body_len; @@ -9570,7 +9570,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError extra_index += 1; const ranges_len = sema.code.extra[extra_index]; extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; const items = sema.code.refSlice(extra_index, items_len); extra_index += items_len; @@ -9647,7 +9647,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError while (scalar_i < scalar_cases_len) : (scalar_i += 1) { const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; extra_index += body_len; @@ -9668,7 +9668,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError extra_index += 1; const ranges_len = sema.code.extra[extra_index]; extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; const items = sema.code.refSlice(extra_index, items_len); extra_index += items_len + body_len; @@ -9732,7 +9732,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError while (scalar_i < scalar_cases_len) : (scalar_i += 1) { const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; extra_index += body_len; @@ -9752,7 +9752,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError extra_index += 1; const ranges_len = sema.code.extra[extra_index]; extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; const items = sema.code.refSlice(extra_index, items_len); extra_index += items_len + body_len; @@ -9832,7 +9832,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError while (scalar_i < scalar_cases_len) : (scalar_i += 1) { const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; const body = sema.code.extra[extra_index..][0..body_len]; extra_index += body_len; @@ -9853,7 +9853,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError extra_index += 1; const ranges_len = sema.code.extra[extra_index]; extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; const items = sema.code.refSlice(extra_index, items_len); extra_index += items_len; @@ -9926,7 +9926,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError while (scalar_i < scalar_cases_len) : (scalar_i += 1) { const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; const body = sema.code.extra[extra_index..][0..body_len]; extra_index += body_len; @@ -9988,7 +9988,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError extra_index += 1; const ranges_len = sema.code.extra[extra_index]; extra_index += 1; - const body_len = sema.code.extra[extra_index]; + const body_len = @truncate(u31, sema.code.extra[extra_index]); extra_index += 1; const items = sema.code.refSlice(extra_index, items_len); extra_index += items_len; diff --git a/src/Zir.zig b/src/Zir.zig index 24248a6533..3ce0b3c81a 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -2990,7 +2990,7 @@ pub const Inst = struct { } if (self.bits.specialProng() != .none) { - const body_len = zir.extra[extra_index]; + const body_len = @truncate(u31, zir.extra[extra_index]); extra_index += 1; const body = zir.extra[extra_index..][0..body_len]; extra_index += body.len; @@ -3000,7 +3000,7 @@ pub const Inst = struct { while (true) : (scalar_i += 1) { const item = @intToEnum(Ref, zir.extra[extra_index]); extra_index += 1; - const body_len = zir.extra[extra_index]; + const body_len = @truncate(u31, zir.extra[extra_index]); extra_index += 1; const body = zir.extra[extra_index..][0..body_len]; extra_index += body.len; @@ -3029,7 +3029,7 @@ pub const Inst = struct { var extra_index: usize = extra_end + 1; if (self.bits.specialProng() != .none) { - const body_len = zir.extra[extra_index]; + const body_len = @truncate(u31, zir.extra[extra_index]); extra_index += 1; const body = zir.extra[extra_index..][0..body_len]; extra_index += body.len; @@ -3038,7 +3038,7 @@ pub const Inst = struct { var scalar_i: usize = 0; while (scalar_i < self.bits.scalar_cases_len) : (scalar_i += 1) { extra_index += 1; - const body_len = zir.extra[extra_index]; + const body_len = @truncate(u31, zir.extra[extra_index]); extra_index += 1; extra_index += body_len; } @@ -3046,7 +3046,7 @@ pub const Inst = struct { while (true) : (multi_i += 1) { const items_len = zir.extra[extra_index]; extra_index += 2; - const body_len = zir.extra[extra_index]; + const body_len = @truncate(u31, zir.extra[extra_index]); extra_index += 1; const items = zir.refSlice(extra_index, items_len); extra_index += items_len; @@ -3858,7 +3858,7 @@ fn findDeclsSwitch( const special_prong = extra.data.bits.specialProng(); if (special_prong != .none) { - const body_len = zir.extra[extra_index]; + const body_len = @truncate(u31, zir.extra[extra_index]); extra_index += 1; const body = zir.extra[extra_index..][0..body_len]; extra_index += body.len; @@ -3871,7 +3871,7 @@ fn findDeclsSwitch( var scalar_i: usize = 0; while (scalar_i < scalar_cases_len) : (scalar_i += 1) { extra_index += 1; - const body_len = zir.extra[extra_index]; + const body_len = @truncate(u31, zir.extra[extra_index]); extra_index += 1; const body = zir.extra[extra_index..][0..body_len]; extra_index += body_len; @@ -3886,7 +3886,7 @@ fn findDeclsSwitch( extra_index += 1; const ranges_len = zir.extra[extra_index]; extra_index += 1; - const body_len = zir.extra[extra_index]; + const body_len = @truncate(u31, zir.extra[extra_index]); extra_index += 1; const items = zir.refSlice(extra_index, items_len); extra_index += items_len; diff --git a/src/print_zir.zig b/src/print_zir.zig index 1d7083e8f1..fcd447f707 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -1868,14 +1868,15 @@ const Writer = struct { else => break :else_prong, }; - const body_len = self.code.extra[extra_index]; + const body_len = @truncate(u31, self.code.extra[extra_index]); + const inline_text = if (self.code.extra[extra_index] >> 31 != 0) "inline " else ""; extra_index += 1; const body = self.code.extra[extra_index..][0..body_len]; extra_index += body.len; try stream.writeAll(",\n"); try stream.writeByteNTimes(' ', self.indent); - try stream.print("{s} => ", .{prong_name}); + try stream.print("{s}{s} => ", .{ inline_text, prong_name }); try self.writeBracedBody(stream, body); } @@ -1885,13 +1886,15 @@ const Writer = struct { while (scalar_i < scalar_cases_len) : (scalar_i += 1) { const item_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]); extra_index += 1; - const body_len = self.code.extra[extra_index]; + const body_len = @truncate(u31, self.code.extra[extra_index]); + const is_inline = self.code.extra[extra_index] >> 31 != 0; extra_index += 1; const body = self.code.extra[extra_index..][0..body_len]; extra_index += body_len; try stream.writeAll(",\n"); try stream.writeByteNTimes(' ', self.indent); + if (is_inline) try stream.writeAll("inline "); try self.writeInstRef(stream, item_ref); try stream.writeAll(" => "); try self.writeBracedBody(stream, body); @@ -1904,13 +1907,15 @@ const Writer = struct { extra_index += 1; const ranges_len = self.code.extra[extra_index]; extra_index += 1; - const body_len = self.code.extra[extra_index]; + const body_len = @truncate(u31, self.code.extra[extra_index]); + const is_inline = self.code.extra[extra_index] >> 31 != 0; extra_index += 1; const items = self.code.refSlice(extra_index, items_len); extra_index += items_len; try stream.writeAll(",\n"); try stream.writeByteNTimes(' ', self.indent); + if (is_inline) try stream.writeAll("inline "); for (items) |item_ref, item_i| { if (item_i != 0) try stream.writeAll(", "); diff --git a/src/stage1/astgen.cpp b/src/stage1/astgen.cpp index 54d9c969a5..9eea2e650e 100644 --- a/src/stage1/astgen.cpp +++ b/src/stage1/astgen.cpp @@ -6987,6 +6987,12 @@ static bool astgen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *sw assert(switch_node->type == NodeTypeSwitchExpr); assert(prong_node->type == NodeTypeSwitchProng); + if (prong_node->data.switch_prong.is_inline) { + exec_add_error_node(ag->codegen, ag->exec, prong_node, + buf_sprintf("inline switch cases not supported by stage1")); + return ag->codegen->invalid_inst_src; + } + AstNode *expr_node = prong_node->data.switch_prong.expr; AstNode *var_symbol_node = prong_node->data.switch_prong.var_symbol; Scope *child_scope; diff --git a/test/cases/compile_errors/inline_underscore_prong.zig b/test/cases/compile_errors/inline_underscore_prong.zig new file mode 100644 index 0000000000..12e20e65bc --- /dev/null +++ b/test/cases/compile_errors/inline_underscore_prong.zig @@ -0,0 +1,15 @@ +const E = enum(u8) { a, b, c, d, _ }; +pub export fn entry() void { + var x: E = .a; + switch (x) { + inline .a, .b => |aorb| @compileLog(aorb), + .c, .d => |cord| @compileLog(cord), + inline _ => {}, + } +} + +// error +// backend=stage2 +// target=native +// +// :7:16: error: cannot inline '_' prong