diff --git a/src/ir.cpp b/src/ir.cpp index 7d8088d5e..3ba58a09b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11395,7 +11395,19 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc } break; case VarClassRequiredAny: - // OK + if (casted_init_value->value.special == ConstValSpecialStatic && + casted_init_value->value.type->id == TypeTableEntryIdFn && + casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) + { + var_class_requires_const = true; + if (!var->src_is_const && !is_comptime_var) { + ErrorMsg *msg = ir_add_error_node(ira, source_node, + buf_sprintf("functions marked inline must be stored in const or comptime var")); + AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node; + add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here")); + result_type = ira->codegen->builtin_types.entry_invalid; + } + } break; } } diff --git a/std/zig/parser.zig b/std/zig/parser.zig index 2aa0773f9..c0708581e 100644 --- a/std/zig/parser.zig +++ b/std/zig/parser.zig @@ -3614,33 +3614,45 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = suffix_op.lhs }); }, ast.NodeSuffixOp.SuffixOp.StructInitializer => |field_inits| { - try stack.append(RenderState { .Text = " }"}); + if (field_inits.len == 0) { + try stack.append(RenderState { .Text = "{}" }); + try stack.append(RenderState { .Expression = suffix_op.lhs }); + continue; + } + try stack.append(RenderState { .Text = "}"}); + try stack.append(RenderState.PrintIndent); + try stack.append(RenderState { .Indent = indent }); var i = field_inits.len; while (i != 0) { i -= 1; const field_init = field_inits.at(i); + try stack.append(RenderState { .Text = ",\n" }); try stack.append(RenderState { .FieldInitializer = field_init }); - try stack.append(RenderState { .Text = " " }); - if (i != 0) { - try stack.append(RenderState { .Text = "," }); - } + try stack.append(RenderState.PrintIndent); } - try stack.append(RenderState { .Text = "{"}); + try stack.append(RenderState { .Indent = indent + indent_delta }); + try stack.append(RenderState { .Text = " {\n"}); try stack.append(RenderState { .Expression = suffix_op.lhs }); }, ast.NodeSuffixOp.SuffixOp.ArrayInitializer => |exprs| { - try stack.append(RenderState { .Text = " }"}); + if (exprs.len == 0) { + try stack.append(RenderState { .Text = "{}" }); + try stack.append(RenderState { .Expression = suffix_op.lhs }); + continue; + } + try stack.append(RenderState { .Text = "}"}); + try stack.append(RenderState.PrintIndent); + try stack.append(RenderState { .Indent = indent }); var i = exprs.len; while (i != 0) { i -= 1; const expr = exprs.at(i); + try stack.append(RenderState { .Text = ",\n" }); try stack.append(RenderState { .Expression = expr }); - try stack.append(RenderState { .Text = " " }); - if (i != 0) { - try stack.append(RenderState { .Text = "," }); - } + try stack.append(RenderState.PrintIndent); } - try stack.append(RenderState { .Text = "{"}); + try stack.append(RenderState { .Indent = indent + indent_delta }); + try stack.append(RenderState { .Text = " {\n"}); try stack.append(RenderState { .Expression = suffix_op.lhs }); }, } @@ -3784,6 +3796,14 @@ pub const Parser = struct { while (i != 0) { i -= 1; const node = fields_and_decls[i]; + switch (node.id) { + ast.Node.Id.StructField, + ast.Node.Id.UnionTag, + ast.Node.Id.EnumTag => { + try stack.append(RenderState { .Text = "," }); + }, + else => { } + } try stack.append(RenderState { .TopLevelDecl = node}); try stack.append(RenderState.PrintIndent); try stack.append(RenderState { @@ -3798,18 +3818,6 @@ pub const Parser = struct { break :blk "\n"; }, }); - - if (i != 0) { - const prev_node = fields_and_decls[i - 1]; - switch (prev_node.id) { - ast.Node.Id.StructField, - ast.Node.Id.UnionTag, - ast.Node.Id.EnumTag => { - try stack.append(RenderState { .Text = "," }); - }, - else => { } - } - } } try stack.append(RenderState { .Indent = indent + indent_delta}); try stack.append(RenderState { .Text = "{"}); @@ -3838,6 +3846,7 @@ pub const Parser = struct { while (i != 0) { i -= 1; const node = decls[i]; + try stack.append(RenderState { .Text = "," }); try stack.append(RenderState { .Expression = node }); try stack.append(RenderState.PrintIndent); try stack.append(RenderState { @@ -3852,10 +3861,6 @@ pub const Parser = struct { break :blk "\n"; }, }); - - if (i != 0) { - try stack.append(RenderState { .Text = "," }); - } } try stack.append(RenderState { .Indent = indent + indent_delta}); try stack.append(RenderState { .Text = "{"}); @@ -3968,6 +3973,7 @@ pub const Parser = struct { while (i != 0) { i -= 1; const node = cases[i]; + try stack.append(RenderState { .Text = ","}); try stack.append(RenderState { .Expression = &node.base}); try stack.append(RenderState.PrintIndent); try stack.append(RenderState { @@ -3982,10 +3988,6 @@ pub const Parser = struct { break :blk "\n"; }, }); - - if (i != 0) { - try stack.append(RenderState { .Text = "," }); - } } try stack.append(RenderState { .Indent = indent + indent_delta}); try stack.append(RenderState { .Text = ") {"}); @@ -4008,7 +4010,8 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = items[i] }); if (i != 0) { - try stack.append(RenderState { .Text = ", " }); + try stack.append(RenderState.PrintIndent); + try stack.append(RenderState { .Text = ",\n" }); } } }, @@ -4600,10 +4603,10 @@ test "zig fmt: precedence" { \\ (a!b)(); \\ !a!b; \\ !(a!b); - \\ !a{ }; - \\ !(a{ }); - \\ a + b{ }; - \\ (a + b){ }; + \\ !a{}; + \\ !(a{}); + \\ a + b{}; + \\ (a + b){}; \\ a << b + c; \\ (a << b) + c; \\ a & b << c; @@ -4740,21 +4743,21 @@ test "zig fmt: struct declaration" { \\ return *self; \\ } \\ - \\ f2: u8 + \\ f2: u8, \\}; \\ \\const Ps = packed struct { \\ a: u8, \\ pub b: u8, \\ - \\ c: u8 + \\ c: u8, \\}; \\ \\const Es = extern struct { \\ a: u8, \\ pub b: u8, \\ - \\ c: u8 + \\ c: u8, \\}; \\ ); @@ -4764,25 +4767,25 @@ test "zig fmt: enum declaration" { try testCanonical( \\const E = enum { \\ Ok, - \\ SomethingElse = 0 + \\ SomethingElse = 0, \\}; \\ \\const E2 = enum(u8) { \\ Ok, \\ SomethingElse = 255, - \\ SomethingThird + \\ SomethingThird, \\}; \\ \\const Ee = extern enum { \\ Ok, \\ SomethingElse, - \\ SomethingThird + \\ SomethingThird, \\}; \\ \\const Ep = packed enum { \\ Ok, \\ SomethingElse, - \\ SomethingThird + \\ SomethingThird, \\}; \\ ); @@ -4794,35 +4797,35 @@ test "zig fmt: union declaration" { \\ Int: u8, \\ Float: f32, \\ None, - \\ Bool: bool + \\ Bool: bool, \\}; \\ \\const Ue = union(enum) { \\ Int: u8, \\ Float: f32, \\ None, - \\ Bool: bool + \\ Bool: bool, \\}; \\ \\const E = enum { \\ Int, \\ Float, \\ None, - \\ Bool + \\ Bool, \\}; \\ \\const Ue2 = union(E) { \\ Int: u8, \\ Float: f32, \\ None, - \\ Bool: bool + \\ Bool: bool, \\}; \\ \\const Eu = extern union { \\ Int: u8, \\ Float: f32, \\ None, - \\ Bool: bool + \\ Bool: bool, \\}; \\ ); @@ -4834,7 +4837,7 @@ test "zig fmt: error set declaration" { \\ A, \\ B, \\ - \\ C + \\ C, \\}; \\ ); @@ -4843,9 +4846,15 @@ test "zig fmt: error set declaration" { test "zig fmt: arrays" { try testCanonical( \\test "test array" { - \\ const a: [2]u8 = [2]u8{ 1, 2 }; - \\ const a: [2]u8 = []u8{ 1, 2 }; - \\ const a: [0]u8 = []u8{ }; + \\ const a: [2]u8 = [2]u8 { + \\ 1, + \\ 2, + \\ }; + \\ const a: [2]u8 = []u8 { + \\ 1, + \\ 2, + \\ }; + \\ const a: [0]u8 = []u8{}; \\} \\ ); @@ -4853,10 +4862,18 @@ test "zig fmt: arrays" { test "zig fmt: container initializers" { try testCanonical( - \\const a1 = []u8{ }; - \\const a2 = []u8{ 1, 2, 3, 4 }; - \\const s1 = S{ }; - \\const s2 = S{ .a = 1, .b = 2 }; + \\const a1 = []u8{}; + \\const a2 = []u8 { + \\ 1, + \\ 2, + \\ 3, + \\ 4, + \\}; + \\const s1 = S{}; + \\const s2 = S { + \\ .a = 1, + \\ .b = 2, + \\}; \\ ); } @@ -4900,31 +4917,34 @@ test "zig fmt: switch" { \\ switch (0) { \\ 0 => {}, \\ 1 => unreachable, - \\ 2, 3 => {}, + \\ 2, + \\ 3 => {}, \\ 4 ... 7 => {}, \\ 1 + 4 * 3 + 22 => {}, \\ else => { \\ const a = 1; \\ const b = a; - \\ } + \\ }, \\ } \\ \\ const res = switch (0) { \\ 0 => 0, \\ 1 => 2, \\ 1 => a = 4, - \\ else => 4 + \\ else => 4, \\ }; \\ \\ const Union = union(enum) { \\ Int: i64, - \\ Float: f64 + \\ Float: f64, \\ }; \\ - \\ const u = Union{ .Int = 0 }; + \\ const u = Union { + \\ .Int = 0, + \\ }; \\ switch (u) { \\ Union.Int => |int| {}, - \\ Union.Float => |*float| unreachable + \\ Union.Float => |*float| unreachable, \\ } \\} \\ @@ -5000,7 +5020,11 @@ test "zig fmt: while" { test "zig fmt: for" { try testCanonical( \\test "for" { - \\ const a = []u8{ 1, 2, 3 }; + \\ const a = []u8 { + \\ 1, + \\ 2, + \\ 3, + \\ }; \\ for (a) |v| { \\ continue; \\ } @@ -5230,3 +5254,12 @@ test "zig fmt: error return" { \\ ); } + +test "zig fmt: struct literals with fields on each line" { + try testCanonical( + \\var self = BufSet { + \\ .hash_map = BufSetHashMap.init(a), + \\}; + \\ + ); +} diff --git a/test/cases/fn.zig b/test/cases/fn.zig index c125d98d8..5388deac1 100644 --- a/test/cases/fn.zig +++ b/test/cases/fn.zig @@ -104,3 +104,10 @@ test "number literal as an argument" { fn numberLiteralArg(a: var) void { assert(a == 3); } + +test "assign inline fn to const variable" { + const a = inlineFn; + a(); +} + +inline fn inlineFn() void { } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 21e384e38..b22816a9a 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,15 @@ const tests = @import("tests.zig"); pub fn addCases(cases: &tests.CompileErrorContext) void { + cases.add("assign inline fn to non-comptime var", + \\export fn entry() void { + \\ var a = b; + \\} + \\inline fn b() void { } + , + ".tmp_source.zig:2:5: error: functions marked inline must be stored in const or comptime var", + ".tmp_source.zig:4:8: note: declared here"); + cases.add("wrong type passed to @panic", \\export fn entry() void { \\ var e = error.Foo;