Skip to content

Commit 2a92b04

Browse files
authored
Merge pull request #14257 from Vexu/compile-errors
compile error improvements and bug fixes
2 parents c2d3722 + d8128c2 commit 2a92b04

File tree

13 files changed

+216
-40
lines changed

13 files changed

+216
-40
lines changed

lib/std/zig/Ast.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
362362
.wrong_equal_var_decl => {
363363
return stream.writeAll("variable initialized with '==' instead of '='");
364364
},
365+
.var_const_decl => {
366+
return stream.writeAll("use 'var' or 'const' to declare variable");
367+
},
365368

366369
.expected_token => {
367370
const found_tag = token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)];
@@ -2743,6 +2746,7 @@ pub const Error = struct {
27432746
c_style_container,
27442747
expected_var_const,
27452748
wrong_equal_var_decl,
2749+
var_const_decl,
27462750

27472751
zig_style_container,
27482752
previous_field,

lib/std/zig/parse.zig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,13 @@ const Parser = struct {
471471
// There is not allowed to be a decl after a field with no comma.
472472
// Report error but recover parser.
473473
try p.warn(.expected_comma_after_field);
474+
if (p.token_tags[p.tok_i] == .semicolon and p.token_tags[identifier] == .identifier) {
475+
try p.warnMsg(.{
476+
.tag = .var_const_decl,
477+
.is_note = true,
478+
.token = identifier,
479+
});
480+
}
474481
p.findNextContainerMember();
475482
continue;
476483
},

lib/std/zig/parser_test.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5238,6 +5238,18 @@ test "zig fmt: missing const/var before local variable" {
52385238
});
52395239
}
52405240

5241+
test "zig fmt: missing const/var before local variable" {
5242+
try testError(
5243+
\\std = foo,
5244+
\\std = foo;
5245+
\\*u32 = foo;
5246+
, &.{
5247+
.expected_comma_after_field,
5248+
.var_const_decl,
5249+
.expected_comma_after_field,
5250+
});
5251+
}
5252+
52415253
test "zig fmt: while continue expr" {
52425254
try testCanonical(
52435255
\\test {

src/AstGen.zig

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,6 +2463,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
24632463
.is_non_null_ptr,
24642464
.is_non_err,
24652465
.is_non_err_ptr,
2466+
.ret_is_non_err,
24662467
.mod_rem,
24672468
.mul,
24682469
.mulwrap,
@@ -4486,9 +4487,24 @@ fn structDeclInner(
44864487
.container_field_align,
44874488
.container_field,
44884489
.@"comptime",
4490+
.test_decl,
44894491
=> continue,
44904492
else => {
4491-
return astgen.failNode(member_node, "tuple declarations cannot contain declarations", .{});
4493+
const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (node_tags[maybe_tuple]) {
4494+
.container_field_init,
4495+
.container_field_align,
4496+
.container_field,
4497+
=> break maybe_tuple,
4498+
else => {},
4499+
} else unreachable;
4500+
return astgen.failNodeNotes(
4501+
member_node,
4502+
"tuple declarations cannot contain declarations",
4503+
.{},
4504+
&[_]u32{
4505+
try astgen.errNoteNode(tuple_member, "tuple field here", .{}),
4506+
},
4507+
);
44924508
},
44934509
}
44944510
};
@@ -7012,7 +7028,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
70127028

70137029
// Emit conditional branch for generating errdefers.
70147030
const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
7015-
const is_non_err = try gz.addUnNode(.is_non_err, result, node);
7031+
const is_non_err = try gz.addUnNode(.ret_is_non_err, result, node);
70167032
const condbr = try gz.addCondBr(.condbr, node);
70177033

70187034
var then_scope = gz.makeSubBlock(scope);

src/Module.zig

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -528,10 +528,10 @@ pub const Decl = struct {
528528
/// Decl is marked alive, then it sends the Decl to the linker. Otherwise it
529529
/// deletes the Decl on the spot.
530530
alive: bool,
531-
/// Whether the Decl is a `usingnamespace` declaration.
532-
is_usingnamespace: bool,
533531
/// If true `name` is already fully qualified.
534532
name_fully_qualified: bool = false,
533+
/// What kind of a declaration is this.
534+
kind: Kind,
535535

536536
/// Represents the position of the code in the output file.
537537
/// This is populated regardless of semantic analysis and code generation.
@@ -551,6 +551,14 @@ pub const Decl = struct {
551551
/// typed_value may need to be regenerated.
552552
dependencies: DepsTable = .{},
553553

554+
pub const Kind = enum {
555+
@"usingnamespace",
556+
@"test",
557+
@"comptime",
558+
named,
559+
anon,
560+
};
561+
554562
pub const Index = enum(u32) {
555563
_,
556564

@@ -4438,7 +4446,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
44384446
// not the struct itself.
44394447
try sema.resolveTypeLayout(decl_tv.ty);
44404448

4441-
if (decl.is_usingnamespace) {
4449+
if (decl.kind == .@"usingnamespace") {
44424450
if (!decl_tv.ty.eql(Type.type, mod)) {
44434451
return sema.fail(&block_scope, ty_src, "expected type, found {}", .{
44444452
decl_tv.ty.fmt(mod),
@@ -4964,42 +4972,47 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
49644972

49654973
// Every Decl needs a name.
49664974
var is_named_test = false;
4975+
var kind: Decl.Kind = .named;
49674976
const decl_name: [:0]const u8 = switch (decl_name_index) {
49684977
0 => name: {
49694978
if (export_bit) {
49704979
const i = iter.usingnamespace_index;
49714980
iter.usingnamespace_index += 1;
4981+
kind = .@"usingnamespace";
49724982
break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i});
49734983
} else {
49744984
const i = iter.comptime_index;
49754985
iter.comptime_index += 1;
4986+
kind = .@"comptime";
49764987
break :name try std.fmt.allocPrintZ(gpa, "comptime_{d}", .{i});
49774988
}
49784989
},
49794990
1 => name: {
49804991
const i = iter.unnamed_test_index;
49814992
iter.unnamed_test_index += 1;
4993+
kind = .@"test";
49824994
break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i});
49834995
},
49844996
2 => name: {
49854997
is_named_test = true;
49864998
const test_name = zir.nullTerminatedString(decl_doccomment_index);
4999+
kind = .@"test";
49875000
break :name try std.fmt.allocPrintZ(gpa, "decltest.{s}", .{test_name});
49885001
},
49895002
else => name: {
49905003
const raw_name = zir.nullTerminatedString(decl_name_index);
49915004
if (raw_name.len == 0) {
49925005
is_named_test = true;
49935006
const test_name = zir.nullTerminatedString(decl_name_index + 1);
5007+
kind = .@"test";
49945008
break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name});
49955009
} else {
49965010
break :name try gpa.dupeZ(u8, raw_name);
49975011
}
49985012
},
49995013
};
50005014
const is_exported = export_bit and decl_name_index != 0;
5001-
const is_usingnamespace = export_bit and decl_name_index == 0;
5002-
if (is_usingnamespace) try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
5015+
if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
50035016

50045017
// We create a Decl for it regardless of analysis status.
50055018
const gop = try namespace.decls.getOrPutContextAdapted(
@@ -5012,8 +5025,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
50125025
if (!gop.found_existing) {
50135026
const new_decl_index = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope);
50145027
const new_decl = mod.declPtr(new_decl_index);
5028+
new_decl.kind = kind;
50155029
new_decl.name = decl_name;
5016-
if (is_usingnamespace) {
5030+
if (kind == .@"usingnamespace") {
50175031
namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub);
50185032
}
50195033
log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace });
@@ -5058,7 +5072,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
50585072
}
50595073
new_decl.is_pub = is_pub;
50605074
new_decl.is_exported = is_exported;
5061-
new_decl.is_usingnamespace = is_usingnamespace;
50625075
new_decl.has_align = has_align;
50635076
new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
50645077
new_decl.zir_decl_index = @intCast(u32, decl_sub_index);
@@ -5076,7 +5089,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
50765089

50775090
decl.is_pub = is_pub;
50785091
decl.is_exported = is_exported;
5079-
decl.is_usingnamespace = is_usingnamespace;
5092+
decl.kind = kind;
50805093
decl.has_align = has_align;
50815094
decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
50825095
decl.zir_decl_index = @intCast(u32, decl_sub_index);
@@ -5635,7 +5648,7 @@ pub fn allocateNewDecl(
56355648
.has_linksection_or_addrspace = false,
56365649
.has_align = false,
56375650
.alive = false,
5638-
.is_usingnamespace = false,
5651+
.kind = .anon,
56395652
};
56405653

56415654
return decl_and_index.decl_index;

src/Sema.zig

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,7 @@ fn analyzeBodyInner(
953953
.int_type => try sema.zirIntType(block, inst),
954954
.is_non_err => try sema.zirIsNonErr(block, inst),
955955
.is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),
956+
.ret_is_non_err => try sema.zirRetIsNonErr(block, inst),
956957
.is_non_null => try sema.zirIsNonNull(block, inst),
957958
.is_non_null_ptr => try sema.zirIsNonNullPtr(block, inst),
958959
.merge_error_sets => try sema.zirMergeErrorSets(block, inst),
@@ -9004,7 +9005,7 @@ fn zirParam(
90049005
else => |e| return e,
90059006
} or comptime_syntax;
90069007
if (sema.inst_map.get(inst)) |arg| {
9007-
if (is_comptime) {
9008+
if (is_comptime and sema.preallocated_new_func != null) {
90089009
// We have a comptime value for this parameter so it should be elided from the
90099010
// function type of the function instruction in this block.
90109011
const coerced_arg = try sema.coerce(block, param_ty, arg, src);
@@ -10288,6 +10289,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1028810289
.ret_err_value_code,
1028910290
.restore_err_ret_index,
1029010291
.is_non_err,
10292+
.ret_is_non_err,
1029110293
.condbr,
1029210294
=> {},
1029310295
else => break,
@@ -16215,11 +16217,54 @@ fn typeInfoDecls(
1621516217
};
1621616218
try sema.queueFullTypeResolution(try declaration_ty.copy(sema.arena));
1621716219

16218-
const decls_len = if (opt_namespace) |ns| ns.decls.count() else 0;
16219-
const decls_vals = try decls_anon_decl.arena().alloc(Value, decls_len);
16220-
for (decls_vals) |*decls_val, i| {
16221-
const decl_index = opt_namespace.?.decls.keys()[i];
16220+
var decl_vals = std.ArrayList(Value).init(sema.gpa);
16221+
defer decl_vals.deinit();
16222+
16223+
var seen_namespaces = std.AutoHashMap(*Namespace, void).init(sema.gpa);
16224+
defer seen_namespaces.deinit();
16225+
16226+
if (opt_namespace) |some| {
16227+
try sema.typeInfoNamespaceDecls(block, decls_anon_decl.arena(), some, &decl_vals, &seen_namespaces);
16228+
}
16229+
16230+
const new_decl = try decls_anon_decl.finish(
16231+
try Type.Tag.array.create(decls_anon_decl.arena(), .{
16232+
.len = decl_vals.items.len,
16233+
.elem_type = declaration_ty,
16234+
}),
16235+
try Value.Tag.aggregate.create(
16236+
decls_anon_decl.arena(),
16237+
try decls_anon_decl.arena().dupe(Value, decl_vals.items),
16238+
),
16239+
0, // default alignment
16240+
);
16241+
return try Value.Tag.slice.create(sema.arena, .{
16242+
.ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16243+
.len = try Value.Tag.int_u64.create(sema.arena, decl_vals.items.len),
16244+
});
16245+
}
16246+
16247+
fn typeInfoNamespaceDecls(
16248+
sema: *Sema,
16249+
block: *Block,
16250+
decls_anon_decl: Allocator,
16251+
namespace: *Namespace,
16252+
decl_vals: *std.ArrayList(Value),
16253+
seen_namespaces: *std.AutoHashMap(*Namespace, void),
16254+
) !void {
16255+
const gop = try seen_namespaces.getOrPut(namespace);
16256+
if (gop.found_existing) return;
16257+
const decls = namespace.decls.keys();
16258+
for (decls) |decl_index| {
1622216259
const decl = sema.mod.declPtr(decl_index);
16260+
if (decl.kind == .@"usingnamespace") {
16261+
try sema.mod.ensureDeclAnalyzed(decl_index);
16262+
var buf: Value.ToTypeBuffer = undefined;
16263+
const new_ns = decl.val.toType(&buf).getNamespace().?;
16264+
try sema.typeInfoNamespaceDecls(block, decls_anon_decl, new_ns, decl_vals, seen_namespaces);
16265+
continue;
16266+
}
16267+
if (decl.kind != .named) continue;
1622316268
const name_val = v: {
1622416269
var anon_decl = try block.startAnonDecl();
1622516270
defer anon_decl.deinit();
@@ -16229,37 +16274,21 @@ fn typeInfoDecls(
1622916274
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
1623016275
0, // default alignment
1623116276
);
16232-
break :v try Value.Tag.slice.create(decls_anon_decl.arena(), .{
16233-
.ptr = try Value.Tag.decl_ref.create(decls_anon_decl.arena(), new_decl),
16234-
.len = try Value.Tag.int_u64.create(decls_anon_decl.arena(), bytes.len),
16277+
break :v try Value.Tag.slice.create(decls_anon_decl, .{
16278+
.ptr = try Value.Tag.decl_ref.create(decls_anon_decl, new_decl),
16279+
.len = try Value.Tag.int_u64.create(decls_anon_decl, bytes.len),
1623516280
});
1623616281
};
1623716282

16238-
const fields = try decls_anon_decl.arena().create([2]Value);
16283+
const fields = try decls_anon_decl.create([2]Value);
1623916284
fields.* = .{
1624016285
//name: []const u8,
1624116286
name_val,
1624216287
//is_pub: bool,
1624316288
Value.makeBool(decl.is_pub),
1624416289
};
16245-
decls_val.* = try Value.Tag.aggregate.create(decls_anon_decl.arena(), fields);
16290+
try decl_vals.append(try Value.Tag.aggregate.create(decls_anon_decl, fields));
1624616291
}
16247-
16248-
const new_decl = try decls_anon_decl.finish(
16249-
try Type.Tag.array.create(decls_anon_decl.arena(), .{
16250-
.len = decls_vals.len,
16251-
.elem_type = declaration_ty,
16252-
}),
16253-
try Value.Tag.aggregate.create(
16254-
decls_anon_decl.arena(),
16255-
try decls_anon_decl.arena().dupe(Value, decls_vals),
16256-
),
16257-
0, // default alignment
16258-
);
16259-
return try Value.Tag.slice.create(sema.arena, .{
16260-
.ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16261-
.len = try Value.Tag.int_u64.create(sema.arena, decls_vals.len),
16262-
});
1626316292
}
1626416293

1626516294
fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -16577,7 +16606,7 @@ fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1657716606
const src = inst_data.src();
1657816607
const operand = try sema.resolveInst(inst_data.operand);
1657916608
try sema.checkErrorType(block, src, sema.typeOf(operand));
16580-
return sema.analyzeIsNonErr(block, inst_data.src(), operand);
16609+
return sema.analyzeIsNonErr(block, src, operand);
1658116610
}
1658216611

1658316612
fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -16592,6 +16621,16 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1659216621
return sema.analyzeIsNonErr(block, src, loaded);
1659316622
}
1659416623

16624+
fn zirRetIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
16625+
const tracy = trace(@src());
16626+
defer tracy.end();
16627+
16628+
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
16629+
const src = inst_data.src();
16630+
const operand = try sema.resolveInst(inst_data.operand);
16631+
return sema.analyzeIsNonErr(block, src, operand);
16632+
}
16633+
1659516634
fn zirCondbr(
1659616635
sema: *Sema,
1659716636
parent_block: *Block,
@@ -29847,6 +29886,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
2984729886
},
2984829887
.have_layout, .fully_resolved_wip, .fully_resolved => return,
2984929888
}
29889+
const prev_status = struct_obj.status;
29890+
errdefer if (struct_obj.status == .layout_wip) {
29891+
struct_obj.status = prev_status;
29892+
};
29893+
2985029894
struct_obj.status = .layout_wip;
2985129895
for (struct_obj.fields.values()) |field, i| {
2985229896
sema.resolveTypeLayout(field.ty) catch |err| switch (err) {
@@ -30026,6 +30070,11 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3002630070
},
3002730071
.have_layout, .fully_resolved_wip, .fully_resolved => return,
3002830072
}
30073+
const prev_status = union_obj.status;
30074+
errdefer if (union_obj.status == .layout_wip) {
30075+
union_obj.status = prev_status;
30076+
};
30077+
3002930078
union_obj.status = .layout_wip;
3003030079
for (union_obj.fields.values()) |field, i| {
3003130080
sema.resolveTypeLayout(field.ty) catch |err| switch (err) {

0 commit comments

Comments
 (0)