authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-18 15:45:11-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-18 15:45:11-07:00
logbea447a6378fbc65eb79f31c5f1770c75850074c
tree95f989734bde6ec6232700933f308f3bf8ffc8e2
parent75c8c4442d1dd6fe43fbef1bfeaded360a98fe51

stage2: fix coercion of error set to error union

When returning an error set or an error union from a function which has an inferred error set, it populates the error names in addition to the set of functions. This can have false negatives, meaning that after checking the map of an unresolved error set, one must do full error set resolution before emitting a compile error.

2 files changed, 30 insertions(+), 30 deletions(-)

src/Sema.zig+25-30
......@@ -1179,6 +1179,18 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T
11791179 return sema.fail(block, src, "remainder division with '{}' and '{}': signed integers and floats must use @rem or @mod", .{ lhs_ty, rhs_ty });
11801180}
11811181
1182fn failWithErrorSetCodeMissing(
1183 sema: *Sema,
1184 block: *Block,
1185 src: LazySrcLoc,
1186 dest_err_set_ty: Type,
1187 src_err_set_ty: Type,
1188) CompileError {
1189 return sema.fail(block, src, "expected type '{}', found type '{}'", .{
1190 dest_err_set_ty, src_err_set_ty,
1191 });
1192}
1193
11821194/// We don't return a pointer to the new error note because the pointer
11831195/// becomes invalid when you add another one.
11841196fn errNote(
......@@ -12858,47 +12870,30 @@ fn wrapErrorUnion(
1285812870 }
1285912871 switch (dest_err_set_ty.tag()) {
1286012872 .anyerror => {},
12861 .error_set_single => {
12873 .error_set_single => ok: {
1286212874 const expected_name = val.castTag(.@"error").?.data.name;
1286312875 const n = dest_err_set_ty.castTag(.error_set_single).?.data;
12864 if (!mem.eql(u8, expected_name, n)) {
12865 return sema.fail(
12866 block,
12867 inst_src,
12868 "expected type '{}', found type '{}'",
12869 .{ dest_err_set_ty, inst_ty },
12870 );
12871 }
12876 if (mem.eql(u8, expected_name, n)) break :ok;
12877 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
1287212878 },
12873 .error_set => {
12879 .error_set => ok: {
1287412880 const expected_name = val.castTag(.@"error").?.data.name;
1287512881 const error_set = dest_err_set_ty.castTag(.error_set).?.data;
1287612882 const names = error_set.names_ptr[0..error_set.names_len];
1287712883 // TODO this is O(N). I'm putting off solving this until we solve inferred
1287812884 // error sets at the same time.
12879 const found = for (names) |name| {
12880 if (mem.eql(u8, expected_name, name)) break true;
12881 } else false;
12882 if (!found) {
12883 return sema.fail(
12884 block,
12885 inst_src,
12886 "expected type '{}', found type '{}'",
12887 .{ dest_err_set_ty, inst_ty },
12888 );
12885 for (names) |name| {
12886 if (mem.eql(u8, expected_name, name)) break :ok;
1288912887 }
12888 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
1289012889 },
12891 .error_set_inferred => {
12890 .error_set_inferred => ok: {
12891 const err_set_payload = dest_err_set_ty.castTag(.error_set_inferred).?.data;
12892 if (err_set_payload.is_anyerror) break :ok;
1289212893 const expected_name = val.castTag(.@"error").?.data.name;
12893 const map = &dest_err_set_ty.castTag(.error_set_inferred).?.data.map;
12894 if (!map.contains(expected_name)) {
12895 return sema.fail(
12896 block,
12897 inst_src,
12898 "expected type '{}', found type '{}'",
12899 .{ dest_err_set_ty, inst_ty },
12900 );
12901 }
12894 if (err_set_payload.map.contains(expected_name)) break :ok;
12895 // TODO error set resolution here before emitting a compile error
12896 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
1290212897 },
1290312898 else => unreachable,
1290412899 }
src/type.zig+5
......@@ -3869,6 +3869,11 @@ pub const Type = extern union {
38693869 .error_set_inferred => {
38703870 const func = err_set_ty.castTag(.error_set_inferred).?.data.func;
38713871 try self.functions.put(gpa, func, {});
3872 var it = func.owner_decl.ty.fnReturnType().errorUnionSet()
3873 .castTag(.error_set_inferred).?.data.map.iterator();
3874 while (it.next()) |entry| {
3875 try self.map.put(gpa, entry.key_ptr.*, {});
3876 }
38723877 },
38733878 .anyerror => {
38743879 self.is_anyerror = true;