| ... | ... | @@ -1820,12 +1820,7 @@ fn analyzeAsType( |
| 1820 | 1820 | } |
| 1821 | 1821 | |
| 1822 | 1822 | pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void { |
| 1823 | | const backend_supports_error_return_tracing = |
| 1824 | | sema.mod.comp.bin_file.options.use_llvm; |
| 1825 | | if (!backend_supports_error_return_tracing) { |
| 1826 | | // TODO implement this feature in all the backends and then delete this branch |
| 1827 | | return; |
| 1828 | | } |
| 1823 | if (!sema.mod.backendSupportsFeature(.error_return_trace)) return; |
| 1829 | 1824 | |
| 1830 | 1825 | assert(!block.is_comptime); |
| 1831 | 1826 | var err_trace_block = block.makeSubBlock(); |
| ... | ... | @@ -2099,16 +2094,12 @@ fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazyS |
| 2099 | 2094 | const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{}); |
| 2100 | 2095 | errdefer msg.destroy(sema.gpa); |
| 2101 | 2096 | |
| 2102 | | const decl_index = container_ty.getOwnerDeclOrNull() orelse break :msg msg; |
| 2103 | | const decl = sema.mod.declPtr(decl_index); |
| 2104 | | const tree = decl.getFileScope().getTree(sema.gpa) catch |err| { |
| 2105 | | log.err("unable to load AST to report compile error: {s}", .{@errorName(err)}); |
| 2106 | | return error.AnalysisFail; |
| 2107 | | }; |
| 2108 | | const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_index); |
| 2109 | | const default_value_src: LazySrcLoc = .{ .node_offset_field_default = field_src.node_offset.x }; |
| 2110 | | |
| 2111 | | try sema.mod.errNoteNonLazy(default_value_src.toSrcLoc(decl), msg, "default value set here", .{}); |
| 2097 | const struct_ty = container_ty.castTag(.@"struct") orelse break :msg msg; |
| 2098 | const default_value_src = struct_ty.data.fieldSrcLoc(sema.mod, .{ |
| 2099 | .index = field_index, |
| 2100 | .range = .value, |
| 2101 | }); |
| 2102 | try sema.mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{}); |
| 2112 | 2103 | break :msg msg; |
| 2113 | 2104 | }; |
| 2114 | 2105 | return sema.failWithOwnedErrorMsg(msg); |
| ... | ... | @@ -2146,15 +2137,61 @@ fn addFieldErrNote( |
| 2146 | 2137 | comptime format: []const u8, |
| 2147 | 2138 | args: anytype, |
| 2148 | 2139 | ) !void { |
| 2140 | @setCold(true); |
| 2149 | 2141 | const mod = sema.mod; |
| 2150 | 2142 | const decl_index = container_ty.getOwnerDecl(); |
| 2151 | 2143 | const decl = mod.declPtr(decl_index); |
| 2152 | | const tree = decl.getFileScope().getTree(sema.gpa) catch |err| { |
| 2153 | | log.err("unable to load AST to report compile error: {s}", .{@errorName(err)}); |
| 2154 | | return error.AnalysisFail; |
| 2144 | |
| 2145 | const field_src = blk: { |
| 2146 | const tree = decl.getFileScope().getTree(sema.gpa) catch |err| { |
| 2147 | log.err("unable to load AST to report compile error: {s}", .{@errorName(err)}); |
| 2148 | break :blk decl.srcLoc(); |
| 2149 | }; |
| 2150 | |
| 2151 | const container_node = decl.relativeToNodeIndex(0); |
| 2152 | const node_tags = tree.nodes.items(.tag); |
| 2153 | var buffer: [2]std.zig.Ast.Node.Index = undefined; |
| 2154 | const container_decl = switch (node_tags[container_node]) { |
| 2155 | .root => tree.containerDeclRoot(), |
| 2156 | .container_decl, |
| 2157 | .container_decl_trailing, |
| 2158 | => tree.containerDecl(container_node), |
| 2159 | .container_decl_two, |
| 2160 | .container_decl_two_trailing, |
| 2161 | => tree.containerDeclTwo(&buffer, container_node), |
| 2162 | .container_decl_arg, |
| 2163 | .container_decl_arg_trailing, |
| 2164 | => tree.containerDeclArg(container_node), |
| 2165 | .tagged_union, |
| 2166 | .tagged_union_trailing, |
| 2167 | => tree.taggedUnion(container_node), |
| 2168 | .tagged_union_two, |
| 2169 | .tagged_union_two_trailing, |
| 2170 | => tree.taggedUnionTwo(&buffer, container_node), |
| 2171 | .tagged_union_enum_tag, |
| 2172 | .tagged_union_enum_tag_trailing, |
| 2173 | => tree.taggedUnionEnumTag(container_node), |
| 2174 | else => break :blk decl.srcLoc(), |
| 2175 | }; |
| 2176 | |
| 2177 | var it_index: usize = 0; |
| 2178 | for (container_decl.ast.members) |member_node| { |
| 2179 | switch (node_tags[member_node]) { |
| 2180 | .container_field_init, |
| 2181 | .container_field_align, |
| 2182 | .container_field, |
| 2183 | => { |
| 2184 | if (it_index == field_index) { |
| 2185 | break :blk decl.nodeOffsetSrcLoc(decl.nodeIndexToRelative(member_node)); |
| 2186 | } |
| 2187 | it_index += 1; |
| 2188 | }, |
| 2189 | else => continue, |
| 2190 | } |
| 2191 | } |
| 2192 | unreachable; |
| 2155 | 2193 | }; |
| 2156 | | const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_index); |
| 2157 | | try mod.errNoteNonLazy(field_src.toSrcLoc(decl), parent, format, args); |
| 2194 | try mod.errNoteNonLazy(field_src, parent, format, args); |
| 2158 | 2195 | } |
| 2159 | 2196 | |
| 2160 | 2197 | fn errMsg( |
| ... | ... | @@ -2868,7 +2905,7 @@ fn zirEnumDecl( |
| 2868 | 2905 | .inlining = null, |
| 2869 | 2906 | .is_comptime = true, |
| 2870 | 2907 | }; |
| 2871 | | defer assert(enum_block.instructions.items.len == 0); // should all be comptime instructions |
| 2908 | defer enum_block.instructions.deinit(sema.gpa); |
| 2872 | 2909 | |
| 2873 | 2910 | if (body.len != 0) { |
| 2874 | 2911 | try sema.analyzeBody(&enum_block, body); |
| ... | ... | @@ -2934,13 +2971,12 @@ fn zirEnumDecl( |
| 2934 | 2971 | |
| 2935 | 2972 | const gop_field = enum_obj.fields.getOrPutAssumeCapacity(field_name); |
| 2936 | 2973 | if (gop_field.found_existing) { |
| 2937 | | const tree = try sema.getAstTree(block); |
| 2938 | | const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i); |
| 2939 | | const other_tag_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_field.index); |
| 2974 | const field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy; |
| 2975 | const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_field.index }).lazy; |
| 2940 | 2976 | const msg = msg: { |
| 2941 | 2977 | const msg = try sema.errMsg(block, field_src, "duplicate enum field '{s}'", .{field_name}); |
| 2942 | 2978 | errdefer msg.destroy(gpa); |
| 2943 | | try sema.errNote(block, other_tag_src, msg, "other field here", .{}); |
| 2979 | try sema.errNote(block, other_field_src, msg, "other field here", .{}); |
| 2944 | 2980 | break :msg msg; |
| 2945 | 2981 | }; |
| 2946 | 2982 | return sema.failWithOwnedErrorMsg(msg); |
| ... | ... | @@ -2949,10 +2985,18 @@ fn zirEnumDecl( |
| 2949 | 2985 | if (has_tag_value) { |
| 2950 | 2986 | const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 2951 | 2987 | extra_index += 1; |
| 2952 | | // TODO: if we need to report an error here, use a source location |
| 2953 | | // that points to this default value expression rather than the struct. |
| 2954 | | // But only resolve the source location if we need to emit a compile error. |
| 2955 | | const tag_val = (try sema.resolveInstConst(block, src, tag_val_ref, "enum tag value must be comptime-known")).val; |
| 2988 | const tag_inst = try sema.resolveInst(tag_val_ref); |
| 2989 | const tag_val = sema.resolveConstValue(block, .unneeded, tag_inst, "") catch |err| switch (err) { |
| 2990 | error.NeededSourceLocation => { |
| 2991 | const value_src = enum_obj.fieldSrcLoc(sema.mod, .{ |
| 2992 | .index = field_i, |
| 2993 | .range = .value, |
| 2994 | }).lazy; |
| 2995 | _ = try sema.resolveConstValue(block, value_src, tag_inst, "enum tag value must be comptime-known"); |
| 2996 | unreachable; |
| 2997 | }, |
| 2998 | else => |e| return e, |
| 2999 | }; |
| 2956 | 3000 | last_tag_val = tag_val; |
| 2957 | 3001 | const copied_tag_val = try tag_val.copy(decl_arena_allocator); |
| 2958 | 3002 | const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{ |
| ... | ... | @@ -2960,11 +3004,13 @@ fn zirEnumDecl( |
| 2960 | 3004 | .mod = mod, |
| 2961 | 3005 | }); |
| 2962 | 3006 | if (gop_val.found_existing) { |
| 2963 | | const tree = try sema.getAstTree(block); |
| 2964 | | const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i); |
| 2965 | | const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_val.index); |
| 3007 | const value_src = enum_obj.fieldSrcLoc(sema.mod, .{ |
| 3008 | .index = field_i, |
| 3009 | .range = .value, |
| 3010 | }).lazy; |
| 3011 | const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_val.index }).lazy; |
| 2966 | 3012 | const msg = msg: { |
| 2967 | | const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)}); |
| 3013 | const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)}); |
| 2968 | 3014 | errdefer msg.destroy(gpa); |
| 2969 | 3015 | try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); |
| 2970 | 3016 | break :msg msg; |
| ... | ... | @@ -2983,9 +3029,8 @@ fn zirEnumDecl( |
| 2983 | 3029 | .mod = mod, |
| 2984 | 3030 | }); |
| 2985 | 3031 | if (gop_val.found_existing) { |
| 2986 | | const tree = try sema.getAstTree(block); |
| 2987 | | const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i); |
| 2988 | | const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop_val.index); |
| 3032 | const field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy; |
| 3033 | const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_val.index }).lazy; |
| 2989 | 3034 | const msg = msg: { |
| 2990 | 3035 | const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)}); |
| 2991 | 3036 | errdefer msg.destroy(gpa); |
| ... | ... | @@ -3003,9 +3048,11 @@ fn zirEnumDecl( |
| 3003 | 3048 | } |
| 3004 | 3049 | |
| 3005 | 3050 | if (!(try sema.intFitsInType(last_tag_val.?, enum_obj.tag_ty, null))) { |
| 3006 | | const tree = try sema.getAstTree(block); |
| 3007 | | const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i); |
| 3008 | | const msg = try sema.errMsg(block, field_src, "enumeration value '{}' too large for type '{}'", .{ |
| 3051 | const value_src = enum_obj.fieldSrcLoc(sema.mod, .{ |
| 3052 | .index = field_i, |
| 3053 | .range = if (has_tag_value) .value else .name, |
| 3054 | }).lazy; |
| 3055 | const msg = try sema.errMsg(block, value_src, "enumeration value '{}' too large for type '{}'", .{ |
| 3009 | 3056 | last_tag_val.?.fmtValue(enum_obj.tag_ty, mod), enum_obj.tag_ty.fmt(mod), |
| 3010 | 3057 | }); |
| 3011 | 3058 | return sema.failWithOwnedErrorMsg(msg); |
| ... | ... | @@ -3319,8 +3366,6 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index |
| 3319 | 3366 | operand_ty.childType() |
| 3320 | 3367 | else |
| 3321 | 3368 | operand_ty; |
| 3322 | | // TODO this should be validated in a more generic instruction that is |
| 3323 | | // emitted for all ifs and whiles with an error union condition. |
| 3324 | 3369 | if (err_union_ty.zigTypeTag() != .ErrorUnion) return; |
| 3325 | 3370 | const payload_ty = err_union_ty.errorUnionPayload().zigTypeTag(); |
| 3326 | 3371 | if (payload_ty != .Void and payload_ty != .NoReturn) { |
| ... | ... | @@ -5908,9 +5953,8 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl { |
| 5908 | 5953 | pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref { |
| 5909 | 5954 | const src = sema.src; |
| 5910 | 5955 | |
| 5911 | | const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; |
| 5912 | | if (!backend_supports_error_return_tracing or !sema.mod.comp.bin_file.options.error_return_tracing) |
| 5913 | | return .none; |
| 5956 | if (!sema.mod.backendSupportsFeature(.error_return_trace)) return .none; |
| 5957 | if (!sema.mod.comp.bin_file.options.error_return_tracing) return .none; |
| 5914 | 5958 | |
| 5915 | 5959 | if (block.is_comptime) |
| 5916 | 5960 | return .none; |
| ... | ... | @@ -6148,8 +6192,7 @@ fn zirCall( |
| 6148 | 6192 | if (sema.owner_func == null or !sema.owner_func.?.calls_or_awaits_errorable_fn) |
| 6149 | 6193 | input_is_error = false; // input was an error type, but no errorable fn's were actually called |
| 6150 | 6194 | |
| 6151 | | const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; |
| 6152 | | if (backend_supports_error_return_tracing and sema.mod.comp.bin_file.options.error_return_tracing and |
| 6195 | if (sema.mod.backendSupportsFeature(.error_return_trace) and sema.mod.comp.bin_file.options.error_return_tracing and |
| 6153 | 6196 | !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace)) |
| 6154 | 6197 | { |
| 6155 | 6198 | const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: { |
| ... | ... | @@ -7183,6 +7226,7 @@ fn instantiateGenericCall( |
| 7183 | 7226 | return err; |
| 7184 | 7227 | }, |
| 7185 | 7228 | else => { |
| 7229 | assert(mod.monomorphed_funcs.remove(new_module_func)); |
| 7186 | 7230 | { |
| 7187 | 7231 | errdefer new_decl_arena.deinit(); |
| 7188 | 7232 | try new_decl.finalizeNewArena(&new_decl_arena); |
| ... | ... | @@ -7936,11 +7980,8 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 7936 | 7980 | |
| 7937 | 7981 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 7938 | 7982 | const result = try block.addTyOp(.intcast, dest_ty, operand); |
| 7939 | | if (block.wantSafety() and |
| 7940 | | !dest_ty.isNonexhaustiveEnum() and |
| 7941 | | // TODO instead of "use_llvm", check a different condition so that backends |
| 7942 | | // can advertise themselves as supporting these extra AIR instructions for safety. |
| 7943 | | sema.mod.comp.bin_file.options.use_llvm) |
| 7983 | if (block.wantSafety() and !dest_ty.isNonexhaustiveEnum() and |
| 7984 | sema.mod.backendSupportsFeature(.is_named_enum_value)) |
| 7944 | 7985 | { |
| 7945 | 7986 | const ok = try block.addUnOp(.is_named_enum_value, result); |
| 7946 | 7987 | try sema.addSafetyCheck(block, ok, .invalid_enum_value); |
| ... | ... | @@ -10658,8 +10699,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10658 | 10699 | return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges); |
| 10659 | 10700 | } |
| 10660 | 10701 | |
| 10661 | | const backend_supports_is_named_enum = sema.mod.comp.bin_file.options.use_llvm; |
| 10662 | | |
| 10663 | 10702 | if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline) { |
| 10664 | 10703 | if (empty_enum) { |
| 10665 | 10704 | return Air.Inst.Ref.void_value; |
| ... | ... | @@ -10670,7 +10709,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10670 | 10709 | if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) { |
| 10671 | 10710 | return Air.Inst.Ref.unreachable_value; |
| 10672 | 10711 | } |
| 10673 | | if (backend_supports_is_named_enum and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and |
| 10712 | if (sema.mod.backendSupportsFeature(.is_named_enum_value) and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and |
| 10674 | 10713 | (!operand_ty.isNonexhaustiveEnum() or union_originally)) |
| 10675 | 10714 | { |
| 10676 | 10715 | try sema.zirDbgStmt(block, cond_dbg_node_index); |
| ... | ... | @@ -11140,7 +11179,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11140 | 11179 | case_block.wip_capture_scope = wip_captures.scope; |
| 11141 | 11180 | case_block.inline_case_capture = .none; |
| 11142 | 11181 | |
| 11143 | | if (backend_supports_is_named_enum and special.body.len != 0 and block.wantSafety() and |
| 11182 | if (sema.mod.backendSupportsFeature(.is_named_enum_value) and special.body.len != 0 and block.wantSafety() and |
| 11144 | 11183 | operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally)) |
| 11145 | 11184 | { |
| 11146 | 11185 | try sema.zirDbgStmt(&case_block, cond_dbg_node_index); |
| ... | ... | @@ -11453,10 +11492,7 @@ fn validateSwitchNoRange( |
| 11453 | 11492 | } |
| 11454 | 11493 | |
| 11455 | 11494 | fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, operand: Air.Inst.Ref) !bool { |
| 11456 | | const this_feature_is_implemented_in_the_backend = |
| 11457 | | sema.mod.comp.bin_file.options.use_llvm; |
| 11458 | | |
| 11459 | | if (!this_feature_is_implemented_in_the_backend) return false; |
| 11495 | if (!sema.mod.backendSupportsFeature(.panic_unwrap_error)) return false; |
| 11460 | 11496 | |
| 11461 | 11497 | const tags = sema.code.instructions.items(.tag); |
| 11462 | 11498 | for (body) |inst| { |
| ... | ... | @@ -16970,20 +17006,17 @@ fn retWithErrTracing( |
| 16970 | 17006 | } |
| 16971 | 17007 | |
| 16972 | 17008 | fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool { |
| 16973 | | // TODO implement this feature in all the backends and then delete this check. |
| 16974 | | const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; |
| 17009 | if (!sema.mod.backendSupportsFeature(.error_return_trace)) return false; |
| 16975 | 17010 | |
| 16976 | 17011 | return fn_ret_ty.isError() and |
| 16977 | | sema.mod.comp.bin_file.options.error_return_tracing and |
| 16978 | | backend_supports_error_return_tracing; |
| 17012 | sema.mod.comp.bin_file.options.error_return_tracing; |
| 16979 | 17013 | } |
| 16980 | 17014 | |
| 16981 | 17015 | fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 16982 | 17016 | const inst_data = sema.code.instructions.items(.data)[inst].save_err_ret_index; |
| 16983 | 17017 | |
| 16984 | | const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; |
| 16985 | | const ok = backend_supports_error_return_tracing and sema.mod.comp.bin_file.options.error_return_tracing; |
| 16986 | | if (!ok) return; |
| 17018 | if (!sema.mod.backendSupportsFeature(.error_return_trace)) return; |
| 17019 | if (!sema.mod.comp.bin_file.options.error_return_tracing) return; |
| 16987 | 17020 | |
| 16988 | 17021 | // This is only relevant at runtime. |
| 16989 | 17022 | if (block.is_comptime or block.is_typeof) return; |
| ... | ... | @@ -17005,11 +17038,9 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) |
| 17005 | 17038 | // This is only relevant at runtime. |
| 17006 | 17039 | if (start_block.is_comptime or start_block.is_typeof) return; |
| 17007 | 17040 | |
| 17008 | | const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; |
| 17009 | | const ok = sema.owner_func.?.calls_or_awaits_errorable_fn and |
| 17010 | | sema.mod.comp.bin_file.options.error_return_tracing and |
| 17011 | | backend_supports_error_return_tracing; |
| 17012 | | if (!ok) return; |
| 17041 | if (!sema.mod.backendSupportsFeature(.error_return_trace)) return; |
| 17042 | if (!sema.owner_func.?.calls_or_awaits_errorable_fn) return; |
| 17043 | if (!sema.mod.comp.bin_file.options.error_return_tracing) return; |
| 17013 | 17044 | |
| 17014 | 17045 | const tracy = trace(@src()); |
| 17015 | 17046 | defer tracy.end(); |
| ... | ... | @@ -17988,14 +18019,10 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { |
| 17988 | 18019 | const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty); |
| 17989 | 18020 | const opt_ptr_stack_trace_ty = try Type.Tag.optional_single_mut_pointer.create(sema.arena, stack_trace_ty); |
| 17990 | 18021 | |
| 17991 | | // TODO implement this feature in all the backends and then delete this check. |
| 17992 | | const backend_supports_error_return_tracing = |
| 17993 | | sema.mod.comp.bin_file.options.use_llvm; |
| 17994 | | |
| 17995 | 18022 | if (sema.owner_func != null and |
| 17996 | 18023 | sema.owner_func.?.calls_or_awaits_errorable_fn and |
| 17997 | 18024 | sema.mod.comp.bin_file.options.error_return_tracing and |
| 17998 | | backend_supports_error_return_tracing) |
| 18025 | sema.mod.backendSupportsFeature(.error_return_trace)) |
| 17999 | 18026 | { |
| 18000 | 18027 | return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); |
| 18001 | 18028 | } |
| ... | ... | @@ -18175,7 +18202,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18175 | 18202 | return sema.addStrLit(block, field_name); |
| 18176 | 18203 | } |
| 18177 | 18204 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 18178 | | if (block.wantSafety() and sema.mod.comp.bin_file.options.use_llvm) { |
| 18205 | if (block.wantSafety() and sema.mod.backendSupportsFeature(.is_named_enum_value)) { |
| 18179 | 18206 | const ok = try block.addUnOp(.is_named_enum_value, casted_operand); |
| 18180 | 18207 | try sema.addSafetyCheck(block, ok, .invalid_enum_value); |
| 18181 | 18208 | } |
| ... | ... | @@ -19469,7 +19496,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 19469 | 19496 | } |
| 19470 | 19497 | |
| 19471 | 19498 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 19472 | | if (block.wantSafety() and !dest_ty.isAnyError() and sema.mod.comp.bin_file.options.use_llvm) { |
| 19499 | if (block.wantSafety() and !dest_ty.isAnyError() and sema.mod.backendSupportsFeature(.error_set_has_value)) { |
| 19473 | 19500 | const err_int_inst = try block.addBitCast(Type.err_int, operand); |
| 19474 | 19501 | const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst); |
| 19475 | 19502 | try sema.addSafetyCheck(block, ok, .invalid_error_code); |
| ... | ... | @@ -21596,7 +21623,7 @@ fn zirVarExtended( |
| 21596 | 21623 | .owner_decl = sema.owner_decl_index, |
| 21597 | 21624 | .init = init_val, |
| 21598 | 21625 | .is_extern = small.is_extern, |
| 21599 | | .is_mutable = true, // TODO get rid of this unused field |
| 21626 | .is_mutable = true, |
| 21600 | 21627 | .is_threadlocal = small.is_threadlocal, |
| 21601 | 21628 | .is_weak_linkage = false, |
| 21602 | 21629 | .lib_name = null, |
| ... | ... | @@ -22075,7 +22102,7 @@ fn zirBuiltinExtern( |
| 22075 | 22102 | .owner_decl = sema.owner_decl_index, |
| 22076 | 22103 | .init = Value.initTag(.unreachable_value), |
| 22077 | 22104 | .is_extern = true, |
| 22078 | | .is_mutable = false, // TODO get rid of this unused field |
| 22105 | .is_mutable = false, |
| 22079 | 22106 | .is_threadlocal = options.is_thread_local, |
| 22080 | 22107 | .is_weak_linkage = options.linkage == .Weak, |
| 22081 | 22108 | .lib_name = null, |
| ... | ... | @@ -22658,11 +22685,7 @@ fn panicWithMsg( |
| 22658 | 22685 | const mod = sema.mod; |
| 22659 | 22686 | const arena = sema.arena; |
| 22660 | 22687 | |
| 22661 | | const this_feature_is_implemented_in_the_backend = |
| 22662 | | mod.comp.bin_file.options.target.ofmt == .c or |
| 22663 | | mod.comp.bin_file.options.use_llvm; |
| 22664 | | if (!this_feature_is_implemented_in_the_backend) { |
| 22665 | | // TODO implement this feature in all the backends and then delete this branch |
| 22688 | if (!mod.backendSupportsFeature(.panic_fn)) { |
| 22666 | 22689 | _ = try block.addNoOp(.breakpoint); |
| 22667 | 22690 | _ = try block.addNoOp(.unreach); |
| 22668 | 22691 | return; |
| ... | ... | @@ -22711,11 +22734,7 @@ fn panicUnwrapError( |
| 22711 | 22734 | defer fail_block.instructions.deinit(gpa); |
| 22712 | 22735 | |
| 22713 | 22736 | { |
| 22714 | | const this_feature_is_implemented_in_the_backend = |
| 22715 | | sema.mod.comp.bin_file.options.use_llvm; |
| 22716 | | |
| 22717 | | if (!this_feature_is_implemented_in_the_backend) { |
| 22718 | | // TODO implement this feature in all the backends and then delete this branch |
| 22737 | if (!sema.mod.backendSupportsFeature(.panic_unwrap_error)) { |
| 22719 | 22738 | _ = try fail_block.addNoOp(.breakpoint); |
| 22720 | 22739 | _ = try fail_block.addNoOp(.unreach); |
| 22721 | 22740 | } else { |
| ... | ... | @@ -22841,18 +22860,12 @@ fn safetyCheckFormatted( |
| 22841 | 22860 | |
| 22842 | 22861 | defer fail_block.instructions.deinit(gpa); |
| 22843 | 22862 | |
| 22844 | | { |
| 22845 | | const this_feature_is_implemented_in_the_backend = |
| 22846 | | sema.mod.comp.bin_file.options.use_llvm; |
| 22847 | | |
| 22848 | | if (!this_feature_is_implemented_in_the_backend) { |
| 22849 | | // TODO implement this feature in all the backends and then delete this branch |
| 22850 | | _ = try fail_block.addNoOp(.breakpoint); |
| 22851 | | _ = try fail_block.addNoOp(.unreach); |
| 22852 | | } else { |
| 22853 | | const panic_fn = try sema.getBuiltin(func); |
| 22854 | | _ = try sema.analyzeCall(&fail_block, panic_fn, sema.src, sema.src, .auto, false, args, null); |
| 22855 | | } |
| 22863 | if (!sema.mod.backendSupportsFeature(.safety_check_formatted)) { |
| 22864 | _ = try fail_block.addNoOp(.breakpoint); |
| 22865 | _ = try fail_block.addNoOp(.unreach); |
| 22866 | } else { |
| 22867 | const panic_fn = try sema.getBuiltin(func); |
| 22868 | _ = try sema.analyzeCall(&fail_block, panic_fn, sema.src, sema.src, .auto, false, args, null); |
| 22856 | 22869 | } |
| 22857 | 22870 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| 22858 | 22871 | } |
| ... | ... | @@ -24517,7 +24530,7 @@ fn coerceExtra( |
| 24517 | 24530 | return block.addBitCast(dest_ty, inst); |
| 24518 | 24531 | } |
| 24519 | 24532 | |
| 24520 | | const is_undef = if (maybe_inst_val) |val| val.isUndef() else false; |
| 24533 | const is_undef = inst_ty.zigTypeTag() == .Undefined; |
| 24521 | 24534 | |
| 24522 | 24535 | switch (dest_ty.zigTypeTag()) { |
| 24523 | 24536 | .Optional => optional: { |
| ... | ... | @@ -30662,14 +30675,13 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 30662 | 30675 | const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name); |
| 30663 | 30676 | if (gop.found_existing) { |
| 30664 | 30677 | const msg = msg: { |
| 30665 | | const tree = try sema.getAstTree(&block_scope); |
| 30666 | | const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i); |
| 30678 | const field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy; |
| 30667 | 30679 | const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{s}'", .{field_name}); |
| 30668 | 30680 | errdefer msg.destroy(gpa); |
| 30669 | 30681 | |
| 30670 | 30682 | const prev_field_index = struct_obj.fields.getIndex(field_name).?; |
| 30671 | | const prev_field_src = enumFieldSrcLoc(decl, tree.*, 0, prev_field_index); |
| 30672 | | try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{}); |
| 30683 | const prev_field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = prev_field_index }); |
| 30684 | try sema.mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{}); |
| 30673 | 30685 | try sema.errNote(&block_scope, src, msg, "struct declared here", .{}); |
| 30674 | 30686 | break :msg msg; |
| 30675 | 30687 | }; |
| ... | ... | @@ -30699,34 +30711,51 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 30699 | 30711 | // so that init values may depend on type layout. |
| 30700 | 30712 | const bodies_index = extra_index; |
| 30701 | 30713 | |
| 30702 | | for (fields) |zir_field, i| { |
| 30703 | | // TODO emit compile errors for invalid field types |
| 30704 | | // such as arrays and pointers inside packed structs. |
| 30714 | for (fields) |zir_field, field_i| { |
| 30705 | 30715 | const field_ty: Type = ty: { |
| 30706 | 30716 | if (zir_field.type_ref != .none) { |
| 30707 | | // TODO: if we need to report an error here, use a source location |
| 30708 | | // that points to this type expression rather than the struct. |
| 30709 | | // But only resolve the source location if we need to emit a compile error. |
| 30710 | | break :ty try sema.resolveType(&block_scope, src, zir_field.type_ref); |
| 30717 | break :ty sema.resolveType(&block_scope, .unneeded, zir_field.type_ref) catch |err| switch (err) { |
| 30718 | error.NeededSourceLocation => { |
| 30719 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 30720 | .index = field_i, |
| 30721 | .range = .type, |
| 30722 | }).lazy; |
| 30723 | _ = try sema.resolveType(&block_scope, ty_src, zir_field.type_ref); |
| 30724 | unreachable; |
| 30725 | }, |
| 30726 | else => |e| return e, |
| 30727 | }; |
| 30711 | 30728 | } |
| 30712 | 30729 | assert(zir_field.type_body_len != 0); |
| 30713 | 30730 | const body = zir.extra[extra_index..][0..zir_field.type_body_len]; |
| 30714 | 30731 | extra_index += body.len; |
| 30715 | 30732 | const ty_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index); |
| 30716 | | break :ty try sema.analyzeAsType(&block_scope, src, ty_ref); |
| 30733 | break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) { |
| 30734 | error.NeededSourceLocation => { |
| 30735 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 30736 | .index = field_i, |
| 30737 | .range = .type, |
| 30738 | }).lazy; |
| 30739 | _ = try sema.analyzeAsType(&block_scope, ty_src, ty_ref); |
| 30740 | unreachable; |
| 30741 | }, |
| 30742 | else => |e| return e, |
| 30743 | }; |
| 30717 | 30744 | }; |
| 30718 | 30745 | if (field_ty.tag() == .generic_poison) { |
| 30719 | 30746 | return error.GenericPoison; |
| 30720 | 30747 | } |
| 30721 | 30748 | |
| 30722 | | const field = &struct_obj.fields.values()[i]; |
| 30749 | const field = &struct_obj.fields.values()[field_i]; |
| 30723 | 30750 | field.ty = try field_ty.copy(decl_arena_allocator); |
| 30724 | 30751 | |
| 30725 | 30752 | if (field_ty.zigTypeTag() == .Opaque) { |
| 30726 | 30753 | const msg = msg: { |
| 30727 | | const tree = try sema.getAstTree(&block_scope); |
| 30728 | | const field_src = enumFieldSrcLoc(decl, tree.*, 0, i); |
| 30729 | | const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); |
| 30754 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 30755 | .index = field_i, |
| 30756 | .range = .type, |
| 30757 | }).lazy; |
| 30758 | const msg = try sema.errMsg(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); |
| 30730 | 30759 | errdefer msg.destroy(sema.gpa); |
| 30731 | 30760 | |
| 30732 | 30761 | try sema.addDeclaredHereNote(msg, field_ty); |
| ... | ... | @@ -30736,9 +30765,11 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 30736 | 30765 | } |
| 30737 | 30766 | if (field_ty.zigTypeTag() == .NoReturn) { |
| 30738 | 30767 | const msg = msg: { |
| 30739 | | const tree = try sema.getAstTree(&block_scope); |
| 30740 | | const field_src = enumFieldSrcLoc(decl, tree.*, 0, i); |
| 30741 | | const msg = try sema.errMsg(&block_scope, field_src, "struct fields cannot be 'noreturn'", .{}); |
| 30768 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 30769 | .index = field_i, |
| 30770 | .range = .type, |
| 30771 | }).lazy; |
| 30772 | const msg = try sema.errMsg(&block_scope, ty_src, "struct fields cannot be 'noreturn'", .{}); |
| 30742 | 30773 | errdefer msg.destroy(sema.gpa); |
| 30743 | 30774 | |
| 30744 | 30775 | try sema.addDeclaredHereNote(msg, field_ty); |
| ... | ... | @@ -30748,12 +30779,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 30748 | 30779 | } |
| 30749 | 30780 | if (struct_obj.layout == .Extern and !try sema.validateExternType(field.ty, .struct_field)) { |
| 30750 | 30781 | const msg = msg: { |
| 30751 | | const tree = try sema.getAstTree(&block_scope); |
| 30752 | | const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i); |
| 30753 | | const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)}); |
| 30782 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 30783 | .index = field_i, |
| 30784 | .range = .type, |
| 30785 | }); |
| 30786 | const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)}); |
| 30754 | 30787 | errdefer msg.destroy(sema.gpa); |
| 30755 | 30788 | |
| 30756 | | try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .struct_field); |
| 30789 | try sema.explainWhyTypeIsNotExtern(msg, ty_src, field.ty, .struct_field); |
| 30757 | 30790 | |
| 30758 | 30791 | try sema.addDeclaredHereNote(msg, field.ty); |
| 30759 | 30792 | break :msg msg; |
| ... | ... | @@ -30761,12 +30794,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 30761 | 30794 | return sema.failWithOwnedErrorMsg(msg); |
| 30762 | 30795 | } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) { |
| 30763 | 30796 | const msg = msg: { |
| 30764 | | const tree = try sema.getAstTree(&block_scope); |
| 30765 | | const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i); |
| 30766 | | const msg = try sema.errMsg(&block_scope, fields_src, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)}); |
| 30797 | const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 30798 | .index = field_i, |
| 30799 | .range = .type, |
| 30800 | }); |
| 30801 | const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)}); |
| 30767 | 30802 | errdefer msg.destroy(sema.gpa); |
| 30768 | 30803 | |
| 30769 | | try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field.ty); |
| 30804 | try sema.explainWhyTypeIsNotPacked(msg, ty_src, field.ty); |
| 30770 | 30805 | |
| 30771 | 30806 | try sema.addDeclaredHereNote(msg, field.ty); |
| 30772 | 30807 | break :msg msg; |
| ... | ... | @@ -30778,7 +30813,17 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 30778 | 30813 | const body = zir.extra[extra_index..][0..zir_field.align_body_len]; |
| 30779 | 30814 | extra_index += body.len; |
| 30780 | 30815 | const align_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index); |
| 30781 | | field.abi_align = try sema.analyzeAsAlign(&block_scope, src, align_ref); |
| 30816 | field.abi_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) { |
| 30817 | error.NeededSourceLocation => { |
| 30818 | const align_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 30819 | .index = field_i, |
| 30820 | .range = .alignment, |
| 30821 | }).lazy; |
| 30822 | _ = try sema.analyzeAsAlign(&block_scope, align_src, align_ref); |
| 30823 | unreachable; |
| 30824 | }, |
| 30825 | else => |e| return e, |
| 30826 | }; |
| 30782 | 30827 | } |
| 30783 | 30828 | |
| 30784 | 30829 | extra_index += zir_field.init_body_len; |
| ... | ... | @@ -30788,26 +30833,30 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 30788 | 30833 | |
| 30789 | 30834 | if (any_inits) { |
| 30790 | 30835 | extra_index = bodies_index; |
| 30791 | | for (fields) |zir_field, i| { |
| 30836 | for (fields) |zir_field, field_i| { |
| 30792 | 30837 | extra_index += zir_field.type_body_len; |
| 30793 | 30838 | extra_index += zir_field.align_body_len; |
| 30794 | 30839 | if (zir_field.init_body_len > 0) { |
| 30795 | 30840 | const body = zir.extra[extra_index..][0..zir_field.init_body_len]; |
| 30796 | 30841 | extra_index += body.len; |
| 30797 | 30842 | const init = try sema.resolveBody(&block_scope, body, struct_obj.zir_index); |
| 30798 | | const field = &struct_obj.fields.values()[i]; |
| 30843 | const field = &struct_obj.fields.values()[field_i]; |
| 30799 | 30844 | const coerced = sema.coerce(&block_scope, field.ty, init, .unneeded) catch |err| switch (err) { |
| 30800 | 30845 | error.NeededSourceLocation => { |
| 30801 | | const tree = try sema.getAstTree(&block_scope); |
| 30802 | | const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i); |
| 30846 | const init_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 30847 | .index = field_i, |
| 30848 | .range = .value, |
| 30849 | }).lazy; |
| 30803 | 30850 | _ = try sema.coerce(&block_scope, field.ty, init, init_src); |
| 30804 | 30851 | unreachable; |
| 30805 | 30852 | }, |
| 30806 | 30853 | else => |e| return e, |
| 30807 | 30854 | }; |
| 30808 | 30855 | const default_val = (try sema.resolveMaybeUndefVal(coerced)) orelse { |
| 30809 | | const tree = try sema.getAstTree(&block_scope); |
| 30810 | | const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i); |
| 30856 | const init_src = struct_obj.fieldSrcLoc(sema.mod, .{ |
| 30857 | .index = field_i, |
| 30858 | .range = .value, |
| 30859 | }).lazy; |
| 30811 | 30860 | return sema.failWithNeededComptime(&block_scope, init_src, "struct field default value must be comptime-known"); |
| 30812 | 30861 | }; |
| 30813 | 30862 | field.default_val = try default_val.copy(decl_arena_allocator); |
| ... | ... | @@ -31023,9 +31072,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 31023 | 31072 | |
| 31024 | 31073 | if (enum_value_map) |map| { |
| 31025 | 31074 | const copied_val = if (tag_ref != .none) blk: { |
| 31026 | | const tag_src = src; // TODO better source location |
| 31027 | | const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, tag_src); |
| 31028 | | const val = try sema.resolveConstValue(&block_scope, tag_src, coerced, "enum tag value must be comptime-known"); |
| 31075 | const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) { |
| 31076 | error.NeededSourceLocation => { |
| 31077 | const val_src = union_obj.fieldSrcLoc(sema.mod, .{ |
| 31078 | .index = field_i, |
| 31079 | .range = .value, |
| 31080 | }).lazy; |
| 31081 | _ = try sema.semaUnionFieldVal(&block_scope, val_src, int_tag_ty, tag_ref); |
| 31082 | unreachable; |
| 31083 | }, |
| 31084 | else => |e| return e, |
| 31085 | }; |
| 31029 | 31086 | last_tag_val = val; |
| 31030 | 31087 | |
| 31031 | 31088 | // This puts the memory into the union arena, not the enum arena, but |
| ... | ... | @@ -31045,9 +31102,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 31045 | 31102 | .mod = mod, |
| 31046 | 31103 | }); |
| 31047 | 31104 | if (gop.found_existing) { |
| 31048 | | const tree = try sema.getAstTree(&block_scope); |
| 31049 | | const field_src = enumFieldSrcLoc(sema.mod.declPtr(block_scope.src_decl), tree.*, src.node_offset.x, field_i); |
| 31050 | | const other_field_src = enumFieldSrcLoc(sema.mod.declPtr(block_scope.src_decl), tree.*, src.node_offset.x, gop.index); |
| 31105 | const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy; |
| 31106 | const other_field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = gop.index }).lazy; |
| 31051 | 31107 | const msg = msg: { |
| 31052 | 31108 | const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, sema.mod)}); |
| 31053 | 31109 | errdefer msg.destroy(gpa); |
| ... | ... | @@ -31069,10 +31125,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 31069 | 31125 | else if (field_type_ref == .none) |
| 31070 | 31126 | Type.initTag(.noreturn) |
| 31071 | 31127 | else |
| 31072 | | // TODO: if we need to report an error here, use a source location |
| 31073 | | // that points to this type expression rather than the union. |
| 31074 | | // But only resolve the source location if we need to emit a compile error. |
| 31075 | | try sema.resolveType(&block_scope, src, field_type_ref); |
| 31128 | sema.resolveType(&block_scope, .unneeded, field_type_ref) catch |err| switch (err) { |
| 31129 | error.NeededSourceLocation => { |
| 31130 | const ty_src = union_obj.fieldSrcLoc(sema.mod, .{ |
| 31131 | .index = field_i, |
| 31132 | .range = .type, |
| 31133 | }).lazy; |
| 31134 | _ = try sema.resolveType(&block_scope, ty_src, field_type_ref); |
| 31135 | unreachable; |
| 31136 | }, |
| 31137 | else => |e| return e, |
| 31138 | }; |
| 31076 | 31139 | |
| 31077 | 31140 | if (field_ty.tag() == .generic_poison) { |
| 31078 | 31141 | return error.GenericPoison; |
| ... | ... | @@ -31081,13 +31144,12 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 31081 | 31144 | const gop = union_obj.fields.getOrPutAssumeCapacity(field_name); |
| 31082 | 31145 | if (gop.found_existing) { |
| 31083 | 31146 | const msg = msg: { |
| 31084 | | const tree = try sema.getAstTree(&block_scope); |
| 31085 | | const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i); |
| 31147 | const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy; |
| 31086 | 31148 | const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{s}'", .{field_name}); |
| 31087 | 31149 | errdefer msg.destroy(gpa); |
| 31088 | 31150 | |
| 31089 | 31151 | const prev_field_index = union_obj.fields.getIndex(field_name).?; |
| 31090 | | const prev_field_src = enumFieldSrcLoc(decl, tree.*, 0, prev_field_index); |
| 31152 | const prev_field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = prev_field_index }).lazy; |
| 31091 | 31153 | try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{}); |
| 31092 | 31154 | try sema.errNote(&block_scope, src, msg, "union declared here", .{}); |
| 31093 | 31155 | break :msg msg; |
| ... | ... | @@ -31099,9 +31161,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 31099 | 31161 | const enum_has_field = names.orderedRemove(field_name); |
| 31100 | 31162 | if (!enum_has_field) { |
| 31101 | 31163 | const msg = msg: { |
| 31102 | | const tree = try sema.getAstTree(&block_scope); |
| 31103 | | const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i); |
| 31104 | | const msg = try sema.errMsg(&block_scope, field_src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) }); |
| 31164 | const ty_src = union_obj.fieldSrcLoc(sema.mod, .{ |
| 31165 | .index = field_i, |
| 31166 | .range = .type, |
| 31167 | }).lazy; |
| 31168 | const msg = try sema.errMsg(&block_scope, ty_src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) }); |
| 31105 | 31169 | errdefer msg.destroy(sema.gpa); |
| 31106 | 31170 | try sema.addDeclaredHereNote(msg, union_obj.tag_ty); |
| 31107 | 31171 | break :msg msg; |
| ... | ... | @@ -31112,9 +31176,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 31112 | 31176 | |
| 31113 | 31177 | if (field_ty.zigTypeTag() == .Opaque) { |
| 31114 | 31178 | const msg = msg: { |
| 31115 | | const tree = try sema.getAstTree(&block_scope); |
| 31116 | | const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i); |
| 31117 | | const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); |
| 31179 | const ty_src = union_obj.fieldSrcLoc(sema.mod, .{ |
| 31180 | .index = field_i, |
| 31181 | .range = .type, |
| 31182 | }).lazy; |
| 31183 | const msg = try sema.errMsg(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); |
| 31118 | 31184 | errdefer msg.destroy(sema.gpa); |
| 31119 | 31185 | |
| 31120 | 31186 | try sema.addDeclaredHereNote(msg, field_ty); |
| ... | ... | @@ -31124,12 +31190,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 31124 | 31190 | } |
| 31125 | 31191 | if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) { |
| 31126 | 31192 | const msg = msg: { |
| 31127 | | const tree = try sema.getAstTree(&block_scope); |
| 31128 | | const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i); |
| 31129 | | const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); |
| 31193 | const ty_src = union_obj.fieldSrcLoc(sema.mod, .{ |
| 31194 | .index = field_i, |
| 31195 | .range = .type, |
| 31196 | }); |
| 31197 | const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); |
| 31130 | 31198 | errdefer msg.destroy(sema.gpa); |
| 31131 | 31199 | |
| 31132 | | try sema.explainWhyTypeIsNotExtern(msg, field_src.toSrcLoc(decl), field_ty, .union_field); |
| 31200 | try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .union_field); |
| 31133 | 31201 | |
| 31134 | 31202 | try sema.addDeclaredHereNote(msg, field_ty); |
| 31135 | 31203 | break :msg msg; |
| ... | ... | @@ -31137,12 +31205,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 31137 | 31205 | return sema.failWithOwnedErrorMsg(msg); |
| 31138 | 31206 | } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) { |
| 31139 | 31207 | const msg = msg: { |
| 31140 | | const tree = try sema.getAstTree(&block_scope); |
| 31141 | | const fields_src = enumFieldSrcLoc(decl, tree.*, 0, field_i); |
| 31142 | | const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); |
| 31208 | const ty_src = union_obj.fieldSrcLoc(sema.mod, .{ |
| 31209 | .index = field_i, |
| 31210 | .range = .type, |
| 31211 | }); |
| 31212 | const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); |
| 31143 | 31213 | errdefer msg.destroy(sema.gpa); |
| 31144 | 31214 | |
| 31145 | | try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field_ty); |
| 31215 | try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty); |
| 31146 | 31216 | |
| 31147 | 31217 | try sema.addDeclaredHereNote(msg, field_ty); |
| 31148 | 31218 | break :msg msg; |
| ... | ... | @@ -31156,10 +31226,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 31156 | 31226 | }; |
| 31157 | 31227 | |
| 31158 | 31228 | if (align_ref != .none) { |
| 31159 | | // TODO: if we need to report an error here, use a source location |
| 31160 | | // that points to this alignment expression rather than the struct. |
| 31161 | | // But only resolve the source location if we need to emit a compile error. |
| 31162 | | gop.value_ptr.abi_align = try sema.resolveAlign(&block_scope, src, align_ref); |
| 31229 | gop.value_ptr.abi_align = sema.resolveAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) { |
| 31230 | error.NeededSourceLocation => { |
| 31231 | const align_src = union_obj.fieldSrcLoc(sema.mod, .{ |
| 31232 | .index = field_i, |
| 31233 | .range = .alignment, |
| 31234 | }).lazy; |
| 31235 | _ = try sema.resolveAlign(&block_scope, align_src, align_ref); |
| 31236 | unreachable; |
| 31237 | }, |
| 31238 | else => |e| return e, |
| 31239 | }; |
| 31163 | 31240 | } else { |
| 31164 | 31241 | gop.value_ptr.abi_align = 0; |
| 31165 | 31242 | } |
| ... | ... | @@ -31184,6 +31261,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 31184 | 31261 | } |
| 31185 | 31262 | } |
| 31186 | 31263 | |
| 31264 | fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Type, tag_ref: Air.Inst.Ref) CompileError!Value { |
| 31265 | const coerced = try sema.coerce(block, int_tag_ty, tag_ref, src); |
| 31266 | return sema.resolveConstValue(block, src, coerced, "enum tag value must be comptime-known"); |
| 31267 | } |
| 31268 | |
| 31187 | 31269 | fn generateUnionTagTypeNumbered( |
| 31188 | 31270 | sema: *Sema, |
| 31189 | 31271 | block: *Block, |
| ... | ... | @@ -31607,102 +31689,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 31607 | 31689 | } |
| 31608 | 31690 | } |
| 31609 | 31691 | |
| 31610 | | fn getAstTree(sema: *Sema, block: *Block) CompileError!*const std.zig.Ast { |
| 31611 | | return block.namespace.file_scope.getTree(sema.gpa) catch |err| { |
| 31612 | | log.err("unable to load AST to report compile error: {s}", .{@errorName(err)}); |
| 31613 | | return error.AnalysisFail; |
| 31614 | | }; |
| 31615 | | } |
| 31616 | | |
| 31617 | | fn enumFieldSrcLoc( |
| 31618 | | decl: *Decl, |
| 31619 | | tree: std.zig.Ast, |
| 31620 | | node_offset: i32, |
| 31621 | | field_index: usize, |
| 31622 | | ) LazySrcLoc { |
| 31623 | | @setCold(true); |
| 31624 | | const field_node = containerFieldNode(decl, tree, node_offset, field_index) orelse |
| 31625 | | return LazySrcLoc.nodeOffset(0); |
| 31626 | | return decl.nodeSrcLoc(field_node); |
| 31627 | | } |
| 31628 | | |
| 31629 | | fn containerFieldInitSrcLoc( |
| 31630 | | decl: *Decl, |
| 31631 | | tree: std.zig.Ast, |
| 31632 | | node_offset: i32, |
| 31633 | | field_index: usize, |
| 31634 | | ) LazySrcLoc { |
| 31635 | | @setCold(true); |
| 31636 | | const node_tags = tree.nodes.items(.tag); |
| 31637 | | const field_node = containerFieldNode(decl, tree, node_offset, field_index) orelse |
| 31638 | | return LazySrcLoc.nodeOffset(0); |
| 31639 | | const node_data = tree.nodes.items(.data)[field_node]; |
| 31640 | | |
| 31641 | | const init_node = switch (node_tags[field_node]) { |
| 31642 | | .container_field_init => node_data.rhs, |
| 31643 | | .container_field => blk: { |
| 31644 | | const extra_data = tree.extraData(node_data.rhs, std.zig.Ast.Node.ContainerField); |
| 31645 | | break :blk extra_data.value_expr; |
| 31646 | | }, |
| 31647 | | else => unreachable, |
| 31648 | | }; |
| 31649 | | |
| 31650 | | return decl.nodeSrcLoc(init_node); |
| 31651 | | } |
| 31652 | | |
| 31653 | | fn containerFieldNode( |
| 31654 | | decl: *Decl, |
| 31655 | | tree: std.zig.Ast, |
| 31656 | | node_offset: i32, |
| 31657 | | field_index: usize, |
| 31658 | | ) ?std.zig.Ast.Node.Index { |
| 31659 | | @setCold(true); |
| 31660 | | const enum_node = decl.relativeToNodeIndex(node_offset); |
| 31661 | | const node_tags = tree.nodes.items(.tag); |
| 31662 | | var buffer: [2]std.zig.Ast.Node.Index = undefined; |
| 31663 | | const container_decl = switch (node_tags[enum_node]) { |
| 31664 | | .root => tree.containerDeclRoot(), |
| 31665 | | |
| 31666 | | .container_decl, |
| 31667 | | .container_decl_trailing, |
| 31668 | | => tree.containerDecl(enum_node), |
| 31669 | | |
| 31670 | | .container_decl_two, |
| 31671 | | .container_decl_two_trailing, |
| 31672 | | => tree.containerDeclTwo(&buffer, enum_node), |
| 31673 | | |
| 31674 | | .container_decl_arg, |
| 31675 | | .container_decl_arg_trailing, |
| 31676 | | => tree.containerDeclArg(enum_node), |
| 31677 | | |
| 31678 | | .tagged_union, |
| 31679 | | .tagged_union_trailing, |
| 31680 | | => tree.taggedUnion(enum_node), |
| 31681 | | .tagged_union_two, |
| 31682 | | .tagged_union_two_trailing, |
| 31683 | | => tree.taggedUnionTwo(&buffer, enum_node), |
| 31684 | | .tagged_union_enum_tag, |
| 31685 | | .tagged_union_enum_tag_trailing, |
| 31686 | | => tree.taggedUnionEnumTag(enum_node), |
| 31687 | | |
| 31688 | | else => return null, |
| 31689 | | }; |
| 31690 | | var it_index: usize = 0; |
| 31691 | | for (container_decl.ast.members) |member_node| { |
| 31692 | | switch (node_tags[member_node]) { |
| 31693 | | .container_field_init, |
| 31694 | | .container_field_align, |
| 31695 | | .container_field, |
| 31696 | | => { |
| 31697 | | if (it_index == field_index) return member_node; |
| 31698 | | it_index += 1; |
| 31699 | | }, |
| 31700 | | |
| 31701 | | else => continue, |
| 31702 | | } |
| 31703 | | } else unreachable; |
| 31704 | | } |
| 31705 | | |
| 31706 | 31692 | /// Returns the type of the AIR instruction. |
| 31707 | 31693 | fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type { |
| 31708 | 31694 | return sema.getTmpAir().typeOf(inst); |
| ... | ... | @@ -31792,14 +31778,6 @@ fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref { |
| 31792 | 31778 | return sema.addConstant(ty, try Value.Tag.int_u64.create(sema.arena, int)); |
| 31793 | 31779 | } |
| 31794 | 31780 | |
| 31795 | | fn addBool(sema: *Sema, ty: Type, boolean: bool) CompileError!Air.Inst.Ref { |
| 31796 | | return switch (ty.zigTypeTag()) { |
| 31797 | | .Vector => sema.addConstant(ty, try Value.Tag.repeated.create(sema.arena, Value.makeBool(boolean))), |
| 31798 | | .Bool => try sema.resolveInst(if (boolean) .bool_true else .bool_false), |
| 31799 | | else => unreachable, |
| 31800 | | }; |
| 31801 | | } |
| 31802 | | |
| 31803 | 31781 | fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref { |
| 31804 | 31782 | return sema.addConstant(ty, Value.undef); |
| 31805 | 31783 | } |
| ... | ... | @@ -32443,27 +32421,6 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 32443 | 32421 | return Value.fromBigInt(sema.arena, result_bigint.toConst()); |
| 32444 | 32422 | } |
| 32445 | 32423 | |
| 32446 | | /// Supports both (vectors of) floats and ints; handles undefined scalars. |
| 32447 | | fn numberAddWrap( |
| 32448 | | sema: *Sema, |
| 32449 | | lhs: Value, |
| 32450 | | rhs: Value, |
| 32451 | | ty: Type, |
| 32452 | | ) !Value { |
| 32453 | | if (ty.zigTypeTag() == .Vector) { |
| 32454 | | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 32455 | | for (result_data) |*scalar, i| { |
| 32456 | | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 32457 | | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 32458 | | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); |
| 32459 | | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); |
| 32460 | | scalar.* = try sema.numberAddWrapScalar(lhs_elem, rhs_elem, ty.scalarType()); |
| 32461 | | } |
| 32462 | | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 32463 | | } |
| 32464 | | return sema.numberAddWrapScalar(lhs, rhs, ty); |
| 32465 | | } |
| 32466 | | |
| 32467 | 32424 | /// Supports both floats and ints; handles undefined. |
| 32468 | 32425 | fn numberAddWrapScalar( |
| 32469 | 32426 | sema: *Sema, |
| ... | ... | @@ -32522,27 +32479,6 @@ fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 32522 | 32479 | return Value.fromBigInt(sema.arena, result_bigint.toConst()); |
| 32523 | 32480 | } |
| 32524 | 32481 | |
| 32525 | | /// Supports both (vectors of) floats and ints; handles undefined scalars. |
| 32526 | | fn numberSubWrap( |
| 32527 | | sema: *Sema, |
| 32528 | | lhs: Value, |
| 32529 | | rhs: Value, |
| 32530 | | ty: Type, |
| 32531 | | ) !Value { |
| 32532 | | if (ty.zigTypeTag() == .Vector) { |
| 32533 | | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 32534 | | for (result_data) |*scalar, i| { |
| 32535 | | var lhs_buf: Value.ElemValueBuffer = undefined; |
| 32536 | | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 32537 | | const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf); |
| 32538 | | const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf); |
| 32539 | | scalar.* = try sema.numberSubWrapScalar(lhs_elem, rhs_elem, ty.scalarType()); |
| 32540 | | } |
| 32541 | | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 32542 | | } |
| 32543 | | return sema.numberSubWrapScalar(lhs, rhs, ty); |
| 32544 | | } |
| 32545 | | |
| 32546 | 32482 | /// Supports both floats and ints; handles undefined. |
| 32547 | 32483 | fn numberSubWrapScalar( |
| 32548 | 32484 | sema: *Sema, |