| author | |
| committer | |
| log | e999a925fade363886538722df7605b01da220d1 |
| tree | a98e8bc43fa699270e33ff2cade7aed5a946b08c |
| parent | aefe4046de9b600bb84cb308ec3afb8f020a2db0 |
| signature |
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 |
| 10146 | 10146 | }), |
| 10147 | 10147 | ); |
| 10148 | 10148 | }, |
| 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 | }, | |
| 10149 | 10230 | .ErrorUnion => { |
| 10150 | 10231 | const field_values = try sema.arena.alloc(Value, 2); |
| 10151 | 10232 | // error_set: type, |
| ... | ... | @@ -10520,7 +10601,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 10520 | 10601 | }), |
| 10521 | 10602 | ); |
| 10522 | 10603 | }, |
| 10523 | .ErrorSet => return sema.fail(block, src, "TODO: implement zirTypeInfo for ErrorSet", .{}), | |
| 10524 | 10604 | .BoundFn => @panic("TODO remove this type from the language and compiler"), |
| 10525 | 10605 | .Frame => return sema.fail(block, src, "TODO: implement zirTypeInfo for Frame", .{}), |
| 10526 | 10606 | .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 { |
| 176 | 176 | fn bar2() (error{}!void) {} |
| 177 | 177 | |
| 178 | 178 | test "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 | |
| 180 | 184 | |
| 181 | 185 | try testErrorUnionType(); |
| 182 | 186 | comptime try testErrorUnionType(); |
| ... | ... | @@ -191,7 +195,11 @@ fn testErrorUnionType() !void { |
| 191 | 195 | } |
| 192 | 196 | |
| 193 | 197 | test "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 | |
| 195 | 203 | |
| 196 | 204 | try testErrorSetType(); |
| 197 | 205 | comptime try testErrorSetType(); |
| ... | ... | @@ -307,7 +315,11 @@ fn foo3(b: usize) Error!usize { |
| 307 | 315 | } |
| 308 | 316 | |
| 309 | 317 | test "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 | |
| 311 | 323 | |
| 312 | 324 | _ = nullLiteral("n") catch |err| handleErrors(err); |
| 313 | 325 | _ = floatLiteral("n") catch |err| handleErrors(err); |
test/behavior/type_info.zig+38-2| ... | ... | @@ -156,8 +156,12 @@ fn testArray() !void { |
| 156 | 156 | } |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | test "type info: error set, error union info" { | |
| 160 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 159 | test "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 | |
| 161 | 165 | |
| 162 | 166 | try testErrorSet(); |
| 163 | 167 | comptime try testErrorSet(); |
| ... | ... | @@ -185,6 +189,38 @@ fn testErrorSet() !void { |
| 185 | 189 | try expect(global_info.ErrorSet == null); |
| 186 | 190 | } |
| 187 | 191 | |
| 192 | test "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 | ||
| 207 | test "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 | ||
| 188 | 224 | test "type info: enum info" { |
| 189 | 225 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 190 | 226 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |