| author | |
| committer | |
| log | a2533e6fca0f28aa64717d8e4c13fe6a780b8b15 |
| tree | 3509a8742dcf45ff99d6d370347bbc4ac08643d7 |
| parent | 6f0601c79336d688c80a3b8592cf758f3c94a636 |
4 files changed, 77 insertions(+), 9 deletions(-)
src/AstGen.zig+11-2| ... | ... | @@ -1282,6 +1282,7 @@ fn arrayInitExpr( |
| 1282 | 1282 | } |
| 1283 | 1283 | } |
| 1284 | 1284 | 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); | |
| 1285 | 1286 | const elem_type = try gz.addUnNode(.elem_type, array_type_inst, array_init.ast.type_expr); |
| 1286 | 1287 | break :inst .{ |
| 1287 | 1288 | .array = array_type_inst, |
| ... | ... | @@ -1495,8 +1496,10 @@ fn structInitExpr( |
| 1495 | 1496 | switch (rl) { |
| 1496 | 1497 | .discard => { |
| 1497 | 1498 | // 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 | } | |
| 1500 | 1503 | for (struct_init.ast.fields) |field_init| { |
| 1501 | 1504 | _ = try expr(gz, scope, .discard, field_init); |
| 1502 | 1505 | } |
| ... | ... | @@ -1505,6 +1508,7 @@ fn structInitExpr( |
| 1505 | 1508 | .ref => { |
| 1506 | 1509 | if (struct_init.ast.type_expr != 0) { |
| 1507 | 1510 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| 1511 | _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node); | |
| 1508 | 1512 | return structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init_ref); |
| 1509 | 1513 | } else { |
| 1510 | 1514 | return structInitExprRlNone(gz, scope, node, struct_init, .struct_init_anon_ref); |
| ... | ... | @@ -1513,6 +1517,7 @@ fn structInitExpr( |
| 1513 | 1517 | .none => { |
| 1514 | 1518 | if (struct_init.ast.type_expr != 0) { |
| 1515 | 1519 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| 1520 | _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node); | |
| 1516 | 1521 | return structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init); |
| 1517 | 1522 | } else { |
| 1518 | 1523 | return structInitExprRlNone(gz, scope, node, struct_init, .struct_init_anon); |
| ... | ... | @@ -1523,6 +1528,7 @@ fn structInitExpr( |
| 1523 | 1528 | return structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init); |
| 1524 | 1529 | } |
| 1525 | 1530 | 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); | |
| 1526 | 1532 | const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init); |
| 1527 | 1533 | return rvalue(gz, rl, result, node); |
| 1528 | 1534 | }, |
| ... | ... | @@ -1573,6 +1579,7 @@ fn structInitExprRlPtr( |
| 1573 | 1579 | return structInitExprRlPtrInner(gz, scope, node, struct_init, base_ptr); |
| 1574 | 1580 | } |
| 1575 | 1581 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| 1582 | _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node); | |
| 1576 | 1583 | |
| 1577 | 1584 | var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr); |
| 1578 | 1585 | defer as_scope.unstack(); |
| ... | ... | @@ -2334,6 +2341,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2334 | 2341 | .closure_capture, |
| 2335 | 2342 | .memcpy, |
| 2336 | 2343 | .memset, |
| 2344 | .validate_array_init_ty, | |
| 2345 | .validate_struct_init_ty, | |
| 2337 | 2346 | => break :b true, |
| 2338 | 2347 | } |
| 2339 | 2348 | } else switch (maybe_unused_result) { |
src/Sema.zig+54-7| ... | ... | @@ -872,6 +872,16 @@ fn analyzeBodyInner( |
| 872 | 872 | i += 1; |
| 873 | 873 | continue; |
| 874 | 874 | }, |
| 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 | }, | |
| 875 | 885 | .validate_struct_init => { |
| 876 | 886 | try sema.zirValidateStructInit(block, inst, false); |
| 877 | 887 | i += 1; |
| ... | ... | @@ -1341,6 +1351,14 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, opt |
| 1341 | 1351 | return sema.fail(block, src, "expected optional type, found {}", .{optional_ty}); |
| 1342 | 1352 | } |
| 1343 | 1353 | |
| 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 | ||
| 1344 | 1362 | fn failWithErrorSetCodeMissing( |
| 1345 | 1363 | sema: *Sema, |
| 1346 | 1364 | block: *Block, |
| ... | ... | @@ -2614,9 +2632,7 @@ fn zirArrayBasePtr( |
| 2614 | 2632 | .Struct => if (elem_ty.isTuple()) return base_ptr, |
| 2615 | 2633 | else => {}, |
| 2616 | 2634 | } |
| 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()); | |
| 2620 | 2636 | } |
| 2621 | 2637 | |
| 2622 | 2638 | fn zirFieldBasePtr( |
| ... | ... | @@ -2640,9 +2656,40 @@ fn zirFieldBasePtr( |
| 2640 | 2656 | .Struct, .Union => return base_ptr, |
| 2641 | 2657 | else => {}, |
| 2642 | 2658 | } |
| 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); | |
| 2646 | 2693 | } |
| 2647 | 2694 | |
| 2648 | 2695 | fn zirValidateStructInit( |
| ... | ... | @@ -10815,7 +10862,7 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 10815 | 10862 | .Struct => return structInitEmpty(sema, block, obj_ty, src, src), |
| 10816 | 10863 | .Array => return arrayInitEmpty(sema, obj_ty), |
| 10817 | 10864 | .Void => return sema.addConstant(obj_ty, Value.void), |
| 10818 | else => unreachable, | |
| 10865 | else => return sema.failWithArrayInitNotSupported(block, src, obj_ty), | |
| 10819 | 10866 | } |
| 10820 | 10867 | } |
| 10821 | 10868 |
src/Zir.zig+10| ... | ... | @@ -655,6 +655,12 @@ pub const Inst = struct { |
| 655 | 655 | /// *?S returns *S |
| 656 | 656 | /// Uses the `un_node` field. |
| 657 | 657 | 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, | |
| 658 | 664 | /// Given a set of `field_ptr` instructions, assumes they are all part of a struct |
| 659 | 665 | /// initialization expression, and emits compile errors for duplicate fields |
| 660 | 666 | /// as well as missing fields, if applicable. |
| ... | ... | @@ -1101,6 +1107,8 @@ pub const Inst = struct { |
| 1101 | 1107 | .switch_cond_ref, |
| 1102 | 1108 | .array_base_ptr, |
| 1103 | 1109 | .field_base_ptr, |
| 1110 | .validate_array_init_ty, | |
| 1111 | .validate_struct_init_ty, | |
| 1104 | 1112 | .validate_struct_init, |
| 1105 | 1113 | .validate_struct_init_comptime, |
| 1106 | 1114 | .validate_array_init, |
| ... | ... | @@ -1356,6 +1364,8 @@ pub const Inst = struct { |
| 1356 | 1364 | .switch_capture_multi_ref = .switch_capture, |
| 1357 | 1365 | .array_base_ptr = .un_node, |
| 1358 | 1366 | .field_base_ptr = .un_node, |
| 1367 | .validate_array_init_ty = .un_node, | |
| 1368 | .validate_struct_init_ty = .un_node, | |
| 1359 | 1369 | .validate_struct_init = .pl_node, |
| 1360 | 1370 | .validate_struct_init_comptime = .pl_node, |
| 1361 | 1371 | .validate_array_init = .pl_node, |
src/print_zir.zig+2| ... | ... | @@ -237,6 +237,8 @@ const Writer = struct { |
| 237 | 237 | .switch_cond_ref, |
| 238 | 238 | .array_base_ptr, |
| 239 | 239 | .field_base_ptr, |
| 240 | .validate_array_init_ty, | |
| 241 | .validate_struct_init_ty, | |
| 240 | 242 | => try self.writeUnNode(stream, inst), |
| 241 | 243 | |
| 242 | 244 | .ref, |