Skip to content

Commit 15e4fc9

Browse files
committed
stage2: validate struct/array init ty
1 parent 23c6bf0 commit 15e4fc9

File tree

4 files changed

+77
-9
lines changed

4 files changed

+77
-9
lines changed

src/AstGen.zig

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,7 @@ fn arrayInitExpr(
12821282
}
12831283
}
12841284
const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
1285+
_ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, node);
12851286
const elem_type = try gz.addUnNode(.elem_type, array_type_inst, array_init.ast.type_expr);
12861287
break :inst .{
12871288
.array = array_type_inst,
@@ -1495,8 +1496,10 @@ fn structInitExpr(
14951496
switch (rl) {
14961497
.discard => {
14971498
// TODO if a type expr is given the fields should be validated for that type
1498-
if (struct_init.ast.type_expr != 0)
1499-
_ = try typeExpr(gz, scope, struct_init.ast.type_expr);
1499+
if (struct_init.ast.type_expr != 0) {
1500+
const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1501+
_ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
1502+
}
15001503
for (struct_init.ast.fields) |field_init| {
15011504
_ = try expr(gz, scope, .discard, field_init);
15021505
}
@@ -1505,6 +1508,7 @@ fn structInitExpr(
15051508
.ref => {
15061509
if (struct_init.ast.type_expr != 0) {
15071510
const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1511+
_ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
15081512
return structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init_ref);
15091513
} else {
15101514
return structInitExprRlNone(gz, scope, node, struct_init, .struct_init_anon_ref);
@@ -1513,6 +1517,7 @@ fn structInitExpr(
15131517
.none => {
15141518
if (struct_init.ast.type_expr != 0) {
15151519
const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1520+
_ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
15161521
return structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init);
15171522
} else {
15181523
return structInitExprRlNone(gz, scope, node, struct_init, .struct_init_anon);
@@ -1523,6 +1528,7 @@ fn structInitExpr(
15231528
return structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init);
15241529
}
15251530
const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1531+
_ = try gz.addUnNode(.validate_struct_init_ty, inner_ty_inst, node);
15261532
const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init);
15271533
return rvalue(gz, rl, result, node);
15281534
},
@@ -1573,6 +1579,7 @@ fn structInitExprRlPtr(
15731579
return structInitExprRlPtrInner(gz, scope, node, struct_init, base_ptr);
15741580
}
15751581
const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1582+
_ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
15761583

15771584
var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr);
15781585
defer as_scope.unstack();
@@ -2334,6 +2341,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
23342341
.closure_capture,
23352342
.memcpy,
23362343
.memset,
2344+
.validate_array_init_ty,
2345+
.validate_struct_init_ty,
23372346
=> break :b true,
23382347
}
23392348
} else switch (maybe_unused_result) {

src/Sema.zig

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,16 @@ fn analyzeBodyInner(
872872
i += 1;
873873
continue;
874874
},
875+
.validate_array_init_ty => {
876+
try sema.validateArrayInitTy(block, inst);
877+
i += 1;
878+
continue;
879+
},
880+
.validate_struct_init_ty => {
881+
try sema.validateStructInitTy(block, inst);
882+
i += 1;
883+
continue;
884+
},
875885
.validate_struct_init => {
876886
try sema.zirValidateStructInit(block, inst, false);
877887
i += 1;
@@ -1341,6 +1351,14 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, opt
13411351
return sema.fail(block, src, "expected optional type, found {}", .{optional_ty});
13421352
}
13431353

1354+
fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
1355+
return sema.fail(block, src, "type '{}' does not support array initialization syntax", .{ty});
1356+
}
1357+
1358+
fn failWithStructInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
1359+
return sema.fail(block, src, "type '{}' does not support struct initialization syntax", .{ty});
1360+
}
1361+
13441362
fn failWithErrorSetCodeMissing(
13451363
sema: *Sema,
13461364
block: *Block,
@@ -2614,9 +2632,7 @@ fn zirArrayBasePtr(
26142632
.Struct => if (elem_ty.isTuple()) return base_ptr,
26152633
else => {},
26162634
}
2617-
return sema.fail(block, src, "type '{}' does not support array initialization syntax", .{
2618-
sema.typeOf(start_ptr).childType(),
2619-
});
2635+
return sema.failWithArrayInitNotSupported(block, src, sema.typeOf(start_ptr).childType());
26202636
}
26212637

26222638
fn zirFieldBasePtr(
@@ -2640,9 +2656,40 @@ fn zirFieldBasePtr(
26402656
.Struct, .Union => return base_ptr,
26412657
else => {},
26422658
}
2643-
return sema.fail(block, src, "type '{}' does not support struct initialization syntax", .{
2644-
sema.typeOf(start_ptr).childType(),
2645-
});
2659+
return sema.failWithStructInitNotSupported(block, src, sema.typeOf(start_ptr).childType());
2660+
}
2661+
2662+
fn validateArrayInitTy(
2663+
sema: *Sema,
2664+
block: *Block,
2665+
inst: Zir.Inst.Index,
2666+
) CompileError!void {
2667+
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
2668+
const src = inst_data.src();
2669+
const ty = try sema.resolveType(block, src, inst_data.operand);
2670+
2671+
switch (ty.zigTypeTag()) {
2672+
.Array, .Vector => return,
2673+
.Struct => if (ty.isTuple()) return,
2674+
else => {},
2675+
}
2676+
return sema.failWithArrayInitNotSupported(block, src, ty);
2677+
}
2678+
2679+
fn validateStructInitTy(
2680+
sema: *Sema,
2681+
block: *Block,
2682+
inst: Zir.Inst.Index,
2683+
) CompileError!void {
2684+
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
2685+
const src = inst_data.src();
2686+
const ty = try sema.resolveType(block, src, inst_data.operand);
2687+
2688+
switch (ty.zigTypeTag()) {
2689+
.Struct, .Union => return,
2690+
else => {},
2691+
}
2692+
return sema.failWithStructInitNotSupported(block, src, ty);
26462693
}
26472694

26482695
fn zirValidateStructInit(
@@ -10815,7 +10862,7 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1081510862
.Struct => return structInitEmpty(sema, block, obj_ty, src, src),
1081610863
.Array => return arrayInitEmpty(sema, obj_ty),
1081710864
.Void => return sema.addConstant(obj_ty, Value.void),
10818-
else => unreachable,
10865+
else => return sema.failWithArrayInitNotSupported(block, src, obj_ty),
1081910866
}
1082010867
}
1082110868

src/Zir.zig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,12 @@ pub const Inst = struct {
655655
/// *?S returns *S
656656
/// Uses the `un_node` field.
657657
field_base_ptr,
658+
/// Checks that the type supports array init syntax.
659+
/// Uses the `un_node` field.
660+
validate_array_init_ty,
661+
/// Checks that the type supports struct init syntax.
662+
/// Uses the `un_node` field.
663+
validate_struct_init_ty,
658664
/// Given a set of `field_ptr` instructions, assumes they are all part of a struct
659665
/// initialization expression, and emits compile errors for duplicate fields
660666
/// as well as missing fields, if applicable.
@@ -1101,6 +1107,8 @@ pub const Inst = struct {
11011107
.switch_cond_ref,
11021108
.array_base_ptr,
11031109
.field_base_ptr,
1110+
.validate_array_init_ty,
1111+
.validate_struct_init_ty,
11041112
.validate_struct_init,
11051113
.validate_struct_init_comptime,
11061114
.validate_array_init,
@@ -1356,6 +1364,8 @@ pub const Inst = struct {
13561364
.switch_capture_multi_ref = .switch_capture,
13571365
.array_base_ptr = .un_node,
13581366
.field_base_ptr = .un_node,
1367+
.validate_array_init_ty = .un_node,
1368+
.validate_struct_init_ty = .un_node,
13591369
.validate_struct_init = .pl_node,
13601370
.validate_struct_init_comptime = .pl_node,
13611371
.validate_array_init = .pl_node,

src/print_zir.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ const Writer = struct {
237237
.switch_cond_ref,
238238
.array_base_ptr,
239239
.field_base_ptr,
240+
.validate_array_init_ty,
241+
.validate_struct_init_ty,
240242
=> try self.writeUnNode(stream, inst),
241243

242244
.ref,

0 commit comments

Comments
 (0)