authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-19 22:31:24+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-20 02:11:06+02:00
loga2533e6fca0f28aa64717d8e4c13fe6a780b8b15
tree3509a8742dcf45ff99d6d370347bbc4ac08643d7
parent6f0601c79336d688c80a3b8592cf758f3c94a636

stage2: validate struct/array init ty


4 files changed, 77 insertions(+), 9 deletions(-)

src/AstGen.zig+11-2
......@@ -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+54-7
......@@ -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
1354fn 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
1358fn 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
13441362fn 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
26222638fn 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
2662fn 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
2679fn 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
26482695fn 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+10
......@@ -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+2
......@@ -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,