| ... | ... | @@ -2344,6 +2344,7 @@ fn zirEnumDecl( |
| 2344 | 2344 | extra_index += 1; |
| 2345 | 2345 | break :blk LazySrcLoc.nodeOffset(node_offset); |
| 2346 | 2346 | } else sema.src; |
| 2347 | const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x }; |
| 2347 | 2348 | |
| 2348 | 2349 | const tag_type_ref = if (small.has_tag_type) blk: { |
| 2349 | 2350 | const tag_type_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| ... | ... | @@ -2369,8 +2370,10 @@ fn zirEnumDecl( |
| 2369 | 2370 | break :blk decls_len; |
| 2370 | 2371 | } else 0; |
| 2371 | 2372 | |
| 2373 | var done = false; |
| 2374 | |
| 2372 | 2375 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); |
| 2373 | | errdefer new_decl_arena.deinit(); |
| 2376 | errdefer if (!done) new_decl_arena.deinit(); |
| 2374 | 2377 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| 2375 | 2378 | |
| 2376 | 2379 | const enum_obj = try new_decl_arena_allocator.create(Module.EnumFull); |
| ... | ... | @@ -2387,7 +2390,7 @@ fn zirEnumDecl( |
| 2387 | 2390 | }, small.name_strategy, "enum", inst); |
| 2388 | 2391 | const new_decl = mod.declPtr(new_decl_index); |
| 2389 | 2392 | new_decl.owns_tv = true; |
| 2390 | | errdefer mod.abortAnonDecl(new_decl_index); |
| 2393 | errdefer if (!done) mod.abortAnonDecl(new_decl_index); |
| 2391 | 2394 | |
| 2392 | 2395 | enum_obj.* = .{ |
| 2393 | 2396 | .owner_decl = new_decl_index, |
| ... | ... | @@ -2406,19 +2409,28 @@ fn zirEnumDecl( |
| 2406 | 2409 | &enum_obj.namespace, new_decl, new_decl.name, |
| 2407 | 2410 | }); |
| 2408 | 2411 | |
| 2412 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2413 | const decl_val = try sema.analyzeDeclVal(block, src, new_decl_index); |
| 2414 | done = true; |
| 2415 | |
| 2416 | var decl_arena = new_decl.value_arena.?.promote(gpa); |
| 2417 | defer new_decl.value_arena.?.* = decl_arena.state; |
| 2418 | const decl_arena_allocator = decl_arena.allocator(); |
| 2419 | |
| 2409 | 2420 | extra_index = try mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl); |
| 2410 | 2421 | |
| 2411 | 2422 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 2412 | 2423 | if (fields_len == 0) { |
| 2413 | 2424 | assert(body.len == 0); |
| 2414 | 2425 | if (tag_type_ref != .none) { |
| 2415 | | // TODO better source location |
| 2416 | | const ty = try sema.resolveType(block, src, tag_type_ref); |
| 2426 | const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref); |
| 2427 | if (ty.zigTypeTag() != .Int and ty.zigTypeTag() != .ComptimeInt) { |
| 2428 | return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)}); |
| 2429 | } |
| 2417 | 2430 | enum_obj.tag_ty = try ty.copy(new_decl_arena_allocator); |
| 2418 | 2431 | enum_obj.tag_ty_inferred = false; |
| 2419 | 2432 | } |
| 2420 | | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2421 | | return sema.analyzeDeclVal(block, src, new_decl_index); |
| 2433 | return decl_val; |
| 2422 | 2434 | } |
| 2423 | 2435 | extra_index += body.len; |
| 2424 | 2436 | |
| ... | ... | @@ -2471,13 +2483,15 @@ fn zirEnumDecl( |
| 2471 | 2483 | try wip_captures.finalize(); |
| 2472 | 2484 | |
| 2473 | 2485 | if (tag_type_ref != .none) { |
| 2474 | | // TODO better source location |
| 2475 | | const ty = try sema.resolveType(block, src, tag_type_ref); |
| 2476 | | enum_obj.tag_ty = try ty.copy(new_decl_arena_allocator); |
| 2486 | const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref); |
| 2487 | if (ty.zigTypeTag() != .Int and ty.zigTypeTag() != .ComptimeInt) { |
| 2488 | return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)}); |
| 2489 | } |
| 2490 | enum_obj.tag_ty = try ty.copy(decl_arena_allocator); |
| 2477 | 2491 | enum_obj.tag_ty_inferred = false; |
| 2478 | 2492 | } else { |
| 2479 | 2493 | const bits = std.math.log2_int_ceil(usize, fields_len); |
| 2480 | | enum_obj.tag_ty = try Type.Tag.int_unsigned.create(new_decl_arena_allocator, bits); |
| 2494 | enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, bits); |
| 2481 | 2495 | enum_obj.tag_ty_inferred = true; |
| 2482 | 2496 | } |
| 2483 | 2497 | } |
| ... | ... | @@ -2488,12 +2502,12 @@ fn zirEnumDecl( |
| 2488 | 2502 | } |
| 2489 | 2503 | } |
| 2490 | 2504 | |
| 2491 | | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| 2505 | try enum_obj.fields.ensureTotalCapacity(decl_arena_allocator, fields_len); |
| 2492 | 2506 | const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| { |
| 2493 | 2507 | if (bag != 0) break true; |
| 2494 | 2508 | } else false; |
| 2495 | 2509 | if (any_values) { |
| 2496 | | try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{ |
| 2510 | try enum_obj.values.ensureTotalCapacityContext(decl_arena_allocator, fields_len, .{ |
| 2497 | 2511 | .ty = enum_obj.tag_ty, |
| 2498 | 2512 | .mod = mod, |
| 2499 | 2513 | }); |
| ... | ... | @@ -2518,7 +2532,7 @@ fn zirEnumDecl( |
| 2518 | 2532 | extra_index += 1; |
| 2519 | 2533 | |
| 2520 | 2534 | // This string needs to outlive the ZIR code. |
| 2521 | | const field_name = try new_decl_arena_allocator.dupe(u8, field_name_zir); |
| 2535 | const field_name = try decl_arena_allocator.dupe(u8, field_name_zir); |
| 2522 | 2536 | |
| 2523 | 2537 | const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name); |
| 2524 | 2538 | if (gop.found_existing) { |
| ... | ... | @@ -2542,7 +2556,7 @@ fn zirEnumDecl( |
| 2542 | 2556 | // But only resolve the source location if we need to emit a compile error. |
| 2543 | 2557 | const tag_val = (try sema.resolveInstConst(block, src, tag_val_ref, "enum tag value must be comptime known")).val; |
| 2544 | 2558 | last_tag_val = tag_val; |
| 2545 | | const copied_tag_val = try tag_val.copy(new_decl_arena_allocator); |
| 2559 | const copied_tag_val = try tag_val.copy(decl_arena_allocator); |
| 2546 | 2560 | enum_obj.values.putAssumeCapacityNoClobberContext(copied_tag_val, {}, .{ |
| 2547 | 2561 | .ty = enum_obj.tag_ty, |
| 2548 | 2562 | .mod = mod, |
| ... | ... | @@ -2553,16 +2567,14 @@ fn zirEnumDecl( |
| 2553 | 2567 | else |
| 2554 | 2568 | Value.zero; |
| 2555 | 2569 | last_tag_val = tag_val; |
| 2556 | | const copied_tag_val = try tag_val.copy(new_decl_arena_allocator); |
| 2570 | const copied_tag_val = try tag_val.copy(decl_arena_allocator); |
| 2557 | 2571 | enum_obj.values.putAssumeCapacityNoClobberContext(copied_tag_val, {}, .{ |
| 2558 | 2572 | .ty = enum_obj.tag_ty, |
| 2559 | 2573 | .mod = mod, |
| 2560 | 2574 | }); |
| 2561 | 2575 | } |
| 2562 | 2576 | } |
| 2563 | | |
| 2564 | | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2565 | | return sema.analyzeDeclVal(block, src, new_decl_index); |
| 2577 | return decl_val; |
| 2566 | 2578 | } |
| 2567 | 2579 | |
| 2568 | 2580 | fn zirUnionDecl( |
| ... | ... | @@ -8551,11 +8563,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8551 | 8563 | if (seen_src != null) continue; |
| 8552 | 8564 | |
| 8553 | 8565 | const field_name = operand_ty.enumFieldName(i); |
| 8554 | | |
| 8555 | | const field_src = src; // TODO better source location |
| 8556 | | try sema.errNote( |
| 8566 | try sema.addFieldErrNote( |
| 8557 | 8567 | block, |
| 8558 | | field_src, |
| 8568 | operand_ty, |
| 8569 | i, |
| 8559 | 8570 | msg, |
| 8560 | 8571 | "unhandled enumeration value: '{s}'", |
| 8561 | 8572 | .{field_name}, |
| ... | ... | @@ -10587,7 +10598,7 @@ fn zirOverflowArithmetic( |
| 10587 | 10598 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 10588 | 10599 | const dest_ty = lhs_ty; |
| 10589 | 10600 | if (dest_ty.scalarType().zigTypeTag() != .Int) { |
| 10590 | | return sema.fail(block, src, "expected vector of integers or integer type, found '{}'", .{dest_ty.fmt(mod)}); |
| 10601 | return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(mod)}); |
| 10591 | 10602 | } |
| 10592 | 10603 | |
| 10593 | 10604 | const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs); |
| ... | ... | @@ -25175,7 +25186,7 @@ fn resolveTypeFieldsUnion( |
| 25175 | 25186 | } |
| 25176 | 25187 | |
| 25177 | 25188 | union_obj.status = .field_types_wip; |
| 25178 | | try semaUnionFields(block, sema.mod, union_obj); |
| 25189 | try semaUnionFields(sema.mod, union_obj); |
| 25179 | 25190 | union_obj.status = .have_field_types; |
| 25180 | 25191 | } |
| 25181 | 25192 | |
| ... | ... | @@ -25462,7 +25473,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 25462 | 25473 | struct_obj.have_field_inits = true; |
| 25463 | 25474 | } |
| 25464 | 25475 | |
| 25465 | | fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 25476 | fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 25466 | 25477 | const tracy = trace(@src()); |
| 25467 | 25478 | defer tracy.end(); |
| 25468 | 25479 | |
| ... | ... | @@ -25567,10 +25578,14 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 25567 | 25578 | var enum_value_map: ?*Module.EnumNumbered.ValueMap = null; |
| 25568 | 25579 | var tag_ty_field_names: ?Module.EnumFull.NameMap = null; |
| 25569 | 25580 | if (tag_type_ref != .none) { |
| 25570 | | const provided_ty = try sema.resolveType(&block_scope, src, tag_type_ref); |
| 25581 | const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x }; |
| 25582 | const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref); |
| 25571 | 25583 | if (small.auto_enum_tag) { |
| 25572 | 25584 | // The provided type is an integer type and we must construct the enum tag type here. |
| 25573 | 25585 | int_tag_ty = provided_ty; |
| 25586 | if (int_tag_ty.zigTypeTag() != .Int and int_tag_ty.zigTypeTag() != .ComptimeInt) { |
| 25587 | return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(sema.mod)}); |
| 25588 | } |
| 25574 | 25589 | union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, fields_len, provided_ty, union_obj); |
| 25575 | 25590 | const enum_obj = union_obj.tag_ty.castTag(.enum_numbered).?.data; |
| 25576 | 25591 | enum_field_names = &enum_obj.fields; |
| ... | ... | @@ -25579,8 +25594,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 25579 | 25594 | // The provided type is the enum tag type. |
| 25580 | 25595 | union_obj.tag_ty = try provided_ty.copy(decl_arena_allocator); |
| 25581 | 25596 | if (union_obj.tag_ty.zigTypeTag() != .Enum) { |
| 25582 | | const tag_ty_src = src; // TODO better source location |
| 25583 | | return sema.fail(block, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(sema.mod)}); |
| 25597 | return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(sema.mod)}); |
| 25584 | 25598 | } |
| 25585 | 25599 | // The fields of the union must match the enum exactly. |
| 25586 | 25600 | // Store a copy of the enum field names so we can check for |
| ... | ... | @@ -25658,7 +25672,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 25658 | 25672 | }); |
| 25659 | 25673 | } else { |
| 25660 | 25674 | const val = if (last_tag_val) |val| |
| 25661 | | try sema.intAdd(block, src, val, Value.one, int_tag_ty) |
| 25675 | try sema.intAdd(&block_scope, src, val, Value.one, int_tag_ty) |
| 25662 | 25676 | else |
| 25663 | 25677 | Value.zero; |
| 25664 | 25678 | last_tag_val = val; |
| ... | ... | @@ -25712,12 +25726,14 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 25712 | 25726 | const enum_has_field = names.orderedRemove(field_name); |
| 25713 | 25727 | if (!enum_has_field) { |
| 25714 | 25728 | const msg = msg: { |
| 25715 | | const msg = try sema.errMsg(block, src, "enum '{}' has no field named '{s}'", .{ union_obj.tag_ty.fmt(sema.mod), field_name }); |
| 25729 | const tree = try sema.getAstTree(&block_scope); |
| 25730 | const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i); |
| 25731 | const msg = try sema.errMsg(&block_scope, field_src, "enum '{}' has no field named '{s}'", .{ union_obj.tag_ty.fmt(sema.mod), field_name }); |
| 25716 | 25732 | errdefer msg.destroy(sema.gpa); |
| 25717 | 25733 | try sema.addDeclaredHereNote(msg, union_obj.tag_ty); |
| 25718 | 25734 | break :msg msg; |
| 25719 | 25735 | }; |
| 25720 | | return sema.failWithOwnedErrorMsg(block, msg); |
| 25736 | return sema.failWithOwnedErrorMsg(&block_scope, msg); |
| 25721 | 25737 | } |
| 25722 | 25738 | } |
| 25723 | 25739 | |
| ... | ... | @@ -25739,18 +25755,18 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 25739 | 25755 | if (tag_ty_field_names) |names| { |
| 25740 | 25756 | if (names.count() > 0) { |
| 25741 | 25757 | const msg = msg: { |
| 25742 | | const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{}); |
| 25758 | const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{}); |
| 25743 | 25759 | errdefer msg.destroy(sema.gpa); |
| 25744 | 25760 | |
| 25745 | 25761 | const enum_ty = union_obj.tag_ty; |
| 25746 | 25762 | for (names.keys()) |field_name| { |
| 25747 | 25763 | const field_index = enum_ty.enumFieldIndex(field_name).?; |
| 25748 | | try sema.addFieldErrNote(block, enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name}); |
| 25764 | try sema.addFieldErrNote(&block_scope, enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name}); |
| 25749 | 25765 | } |
| 25750 | 25766 | try sema.addDeclaredHereNote(msg, union_obj.tag_ty); |
| 25751 | 25767 | break :msg msg; |
| 25752 | 25768 | }; |
| 25753 | | return sema.failWithOwnedErrorMsg(block, msg); |
| 25769 | return sema.failWithOwnedErrorMsg(&block_scope, msg); |
| 25754 | 25770 | } |
| 25755 | 25771 | } |
| 25756 | 25772 | } |