authorgravatar for mitchell.hashimoto@gmail.comMitchell Hashimoto <mitchell.hashimoto@gmail.com> 2022-02-26 19:59:06-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-26 22:59:06-05:00
loge999a925fade363886538722df7605b01da220d1
treea98e8bc43fa699270e33ff2cade7aed5a946b08c
parentaefe4046de9b600bb84cb308ec3afb8f020a2db0
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

stage2: @TypeInfo for error sets (#10998)


3 files changed, 134 insertions(+), 6 deletions(-)

src/Sema.zig+81-1
......@@ -10146,6 +10146,87 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1014610146 }),
1014710147 );
1014810148 },
10149 .ErrorSet => {
10150 var fields_anon_decl = try block.startAnonDecl(src);
10151 defer fields_anon_decl.deinit();
10152
10153 // Get the Error type
10154 const error_field_ty = t: {
10155 const set_field_ty_decl = (try sema.namespaceLookup(
10156 block,
10157 src,
10158 type_info_ty.getNamespace().?,
10159 "Error",
10160 )).?;
10161 try sema.mod.declareDeclDependency(sema.owner_decl, set_field_ty_decl);
10162 try sema.ensureDeclAnalyzed(set_field_ty_decl);
10163 var buffer: Value.ToTypeBuffer = undefined;
10164 break :t try set_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
10165 };
10166
10167 // If the error set is inferred it has to be resolved at this point
10168 if (ty.castTag(.error_set_inferred)) |payload| {
10169 try sema.resolveInferredErrorSet(payload.data);
10170 }
10171
10172 // Build our list of Error values
10173 // Optional value is only null if anyerror
10174 // Value can be zero-length slice otherwise
10175 const error_field_vals: ?[]Value = if (ty.isAnyError()) null else blk: {
10176 const names = ty.errorSetNames();
10177 const vals = try fields_anon_decl.arena().alloc(Value, names.len);
10178 for (vals) |*field_val, i| {
10179 const name = names[i];
10180 const name_val = v: {
10181 var anon_decl = try block.startAnonDecl(src);
10182 defer anon_decl.deinit();
10183 const bytes = try anon_decl.arena().dupeZ(u8, name);
10184 const new_decl = try anon_decl.finish(
10185 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
10186 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
10187 );
10188 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
10189 };
10190
10191 const error_field_fields = try fields_anon_decl.arena().create([1]Value);
10192 error_field_fields.* = .{
10193 // name: []const u8,
10194 name_val,
10195 };
10196
10197 field_val.* = try Value.Tag.@"struct".create(
10198 fields_anon_decl.arena(),
10199 error_field_fields,
10200 );
10201 }
10202
10203 break :blk vals;
10204 };
10205
10206 // Build our ?[]const Error value
10207 const errors_val = if (error_field_vals) |vals| v: {
10208 const new_decl = try fields_anon_decl.finish(
10209 try Type.Tag.array.create(fields_anon_decl.arena(), .{
10210 .len = vals.len,
10211 .elem_type = error_field_ty,
10212 }),
10213 try Value.Tag.array.create(
10214 fields_anon_decl.arena(),
10215 vals,
10216 ),
10217 );
10218 break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
10219 } else Value.@"null";
10220
10221 // Construct TypeInfo{ .ErrorSet = errors_val }
10222 return sema.addConstant(
10223 type_info_ty,
10224 try Value.Tag.@"union".create(sema.arena, .{
10225 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ErrorSet)),
10226 .val = errors_val,
10227 }),
10228 );
10229 },
1014910230 .ErrorUnion => {
1015010231 const field_values = try sema.arena.alloc(Value, 2);
1015110232 // error_set: type,
......@@ -10520,7 +10601,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1052010601 }),
1052110602 );
1052210603 },
10523 .ErrorSet => return sema.fail(block, src, "TODO: implement zirTypeInfo for ErrorSet", .{}),
1052410604 .BoundFn => @panic("TODO remove this type from the language and compiler"),
1052510605 .Frame => return sema.fail(block, src, "TODO: implement zirTypeInfo for Frame", .{}),
1052610606 .AnyFrame => return sema.fail(block, src, "TODO: implement zirTypeInfo for AnyFrame", .{}),
test/behavior/error.zig+15-3
......@@ -176,7 +176,11 @@ fn foo2(f: fn () anyerror!void) void {
176176fn bar2() (error{}!void) {}
177177
178178test "error union type " {
179 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
180 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
182 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
183 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
180184
181185 try testErrorUnionType();
182186 comptime try testErrorUnionType();
......@@ -191,7 +195,11 @@ fn testErrorUnionType() !void {
191195}
192196
193197test "error set type" {
194 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
198 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
199 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
200 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
201 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
195203
196204 try testErrorSetType();
197205 comptime try testErrorSetType();
......@@ -307,7 +315,11 @@ fn foo3(b: usize) Error!usize {
307315}
308316
309317test "error: Infer error set from literals" {
310 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
319 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
321 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
322 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
311323
312324 _ = nullLiteral("n") catch |err| handleErrors(err);
313325 _ = floatLiteral("n") catch |err| handleErrors(err);
test/behavior/type_info.zig+38-2
......@@ -156,8 +156,12 @@ fn testArray() !void {
156156 }
157157}
158158
159test "type info: error set, error union info" {
160 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
159test "type info: error set, error union info, anyerror" {
160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
161 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
164 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
161165
162166 try testErrorSet();
163167 comptime try testErrorSet();
......@@ -185,6 +189,38 @@ fn testErrorSet() !void {
185189 try expect(global_info.ErrorSet == null);
186190}
187191
192test "type info: error set single value" {
193 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
194 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
195 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
196 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
197 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
198
199 const TestSet = error.One;
200
201 const error_set_info = @typeInfo(@TypeOf(TestSet));
202 try expect(error_set_info == .ErrorSet);
203 try expect(error_set_info.ErrorSet.?.len == 1);
204 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
205}
206
207test "type info: error set merged" {
208 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
209 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
210 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
211 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
212 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
213
214 const TestSet = error{ One, Two } || error{Three};
215
216 const error_set_info = @typeInfo(TestSet);
217 try expect(error_set_info == .ErrorSet);
218 try expect(error_set_info.ErrorSet.?.len == 3);
219 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
220 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
221 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
222}
223
188224test "type info: enum info" {
189225 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
190226 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;