authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-12 13:22:27-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-08-12 13:22:27-04:00
loga0670e748ec4914f7fc198422d0815e71e90a54f
tree4f32c8520102c445752ba882657fb7e9a67854c8
parent394d287778971c3d06fc401e688fc048cdf9860a
parent16c11988587ad78cd47ec571e1120c052abd47ed
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #9166 from joachimschmidt557/stage2

stage2 Sema: Add error notes to unresolvable peer types

3 files changed, 105 insertions(+), 11 deletions(-)

src/Module.zig+51
......@@ -4399,6 +4399,57 @@ pub const SwitchProngSrc = union(enum) {
43994399 }
44004400};
44014401
4402pub const PeerTypeCandidateSrc = union(enum) {
4403 /// Do not print out error notes for candidate sources
4404 none: void,
4405 /// When we want to know the the src of candidate i, look up at
4406 /// index i in this slice
4407 override: []LazySrcLoc,
4408 /// resolvePeerTypes originates from a @TypeOf(...) call
4409 typeof_builtin_call_node_offset: i32,
4410
4411 pub fn resolve(
4412 self: PeerTypeCandidateSrc,
4413 gpa: *Allocator,
4414 decl: *Decl,
4415 candidates: usize,
4416 candidate_i: usize,
4417 ) ?LazySrcLoc {
4418 @setCold(true);
4419
4420 switch (self) {
4421 .none => {
4422 return null;
4423 },
4424 .override => |candidate_srcs| {
4425 return candidate_srcs[candidate_i];
4426 },
4427 .typeof_builtin_call_node_offset => |node_offset| {
4428 if (candidates <= 2) {
4429 switch (candidate_i) {
4430 0 => return LazySrcLoc{ .node_offset_builtin_call_arg0 = node_offset },
4431 1 => return LazySrcLoc{ .node_offset_builtin_call_arg1 = node_offset },
4432 else => unreachable,
4433 }
4434 }
4435
4436 const tree = decl.namespace.file_scope.getTree(gpa) catch |err| {
4437 // In this case we emit a warning + a less precise source location.
4438 log.warn("unable to load {s}: {s}", .{
4439 decl.namespace.file_scope.sub_file_path, @errorName(err),
4440 });
4441 return LazySrcLoc{ .node_offset = 0 };
4442 };
4443 const node = decl.relativeToNodeIndex(node_offset);
4444 const node_datas = tree.nodes.items(.data);
4445 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
4446
4447 return LazySrcLoc{ .node_abs = params[candidate_i] };
4448 },
4449 }
4450 }
4451};
4452
44024453pub fn analyzeStructFields(mod: *Module, struct_obj: *Struct) CompileError!void {
44034454 const tracy = trace(@src());
44044455 defer tracy.end();
src/Sema.zig+44-9
......@@ -1496,7 +1496,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
14961496
14971497 if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| {
14981498 const peer_inst_list = inferred_alloc.data.stored_inst_list.items;
1499 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list);
1499 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);
15001500 if (var_is_mut) {
15011501 try sema.validateVarType(block, ty_src, final_elem_ty);
15021502 }
......@@ -2103,7 +2103,7 @@ fn analyzeBlockBody(
21032103 // Need to set the type and emit the Block instruction. This allows machine code generation
21042104 // to emit a jump instruction to after the block when it encounters the break.
21052105 try parent_block.instructions.append(gpa, merges.block_inst);
2106 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items);
2106 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .none);
21072107 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
21082108 child_block.instructions.items.len);
21092109 sema.air_instructions.items(.data)[merges.block_inst] = .{ .ty_pl = .{
......@@ -5325,7 +5325,7 @@ fn zirBitwise(
53255325 const rhs_ty = sema.typeOf(rhs);
53265326
53275327 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
5328 const resolved_type = try sema.resolvePeerTypes(block, src, instructions);
5328 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
53295329 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
53305330 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
53315331
......@@ -5506,7 +5506,7 @@ fn analyzeArithmetic(
55065506 };
55075507
55085508 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
5509 const resolved_type = try sema.resolvePeerTypes(block, src, instructions);
5509 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
55105510 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
55115511 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
55125512
......@@ -5817,7 +5817,7 @@ fn analyzeCmp(
58175817 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);
58185818 }
58195819 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
5820 const resolved_type = try sema.resolvePeerTypes(block, src, instructions);
5820 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
58215821 if (!resolved_type.isSelfComparable(is_equality_cmp)) {
58225822 return sema.mod.fail(&block.base, src, "{s} operator not allowed for type '{}'", .{
58235823 @tagName(op), resolved_type,
......@@ -6027,7 +6027,7 @@ fn zirTypeofPeer(
60276027 inst_list[i] = sema.resolveInst(arg_ref);
60286028 }
60296029
6030 const result_type = try sema.resolvePeerTypes(block, src, inst_list);
6030 const result_type = try sema.resolvePeerTypes(block, src, inst_list, .{ .typeof_builtin_call_node_offset = extra.data.src_node });
60316031 return sema.addType(result_type);
60326032}
60336033
......@@ -8966,6 +8966,7 @@ fn resolvePeerTypes(
89668966 block: *Scope.Block,
89678967 src: LazySrcLoc,
89688968 instructions: []Air.Inst.Ref,
8969 candidate_srcs: Module.PeerTypeCandidateSrc,
89698970) !Type {
89708971 if (instructions.len == 0)
89718972 return Type.initTag(.noreturn);
......@@ -8976,7 +8977,8 @@ fn resolvePeerTypes(
89768977 const target = sema.mod.getTarget();
89778978
89788979 var chosen = instructions[0];
8979 for (instructions[1..]) |candidate| {
8980 var chosen_i: usize = 0;
8981 for (instructions[1..]) |candidate, candidate_i| {
89808982 const candidate_ty = sema.typeOf(candidate);
89818983 const chosen_ty = sema.typeOf(chosen);
89828984 if (candidate_ty.eql(chosen_ty))
......@@ -8985,12 +8987,14 @@ fn resolvePeerTypes(
89858987 continue;
89868988 if (chosen_ty.zigTypeTag() == .NoReturn) {
89878989 chosen = candidate;
8990 chosen_i = candidate_i + 1;
89888991 continue;
89898992 }
89908993 if (candidate_ty.zigTypeTag() == .Undefined)
89918994 continue;
89928995 if (chosen_ty.zigTypeTag() == .Undefined) {
89938996 chosen = candidate;
8997 chosen_i = candidate_i + 1;
89948998 continue;
89958999 }
89969000 if (chosen_ty.isInt() and
......@@ -8999,18 +9003,21 @@ fn resolvePeerTypes(
89999003 {
90009004 if (chosen_ty.intInfo(target).bits < candidate_ty.intInfo(target).bits) {
90019005 chosen = candidate;
9006 chosen_i = candidate_i + 1;
90029007 }
90039008 continue;
90049009 }
90059010 if (chosen_ty.isFloat() and candidate_ty.isFloat()) {
90069011 if (chosen_ty.floatBits(target) < candidate_ty.floatBits(target)) {
90079012 chosen = candidate;
9013 chosen_i = candidate_i + 1;
90089014 }
90099015 continue;
90109016 }
90119017
90129018 if (chosen_ty.zigTypeTag() == .ComptimeInt and candidate_ty.isInt()) {
90139019 chosen = candidate;
9020 chosen_i = candidate_i + 1;
90149021 continue;
90159022 }
90169023
......@@ -9020,6 +9027,7 @@ fn resolvePeerTypes(
90209027
90219028 if (chosen_ty.zigTypeTag() == .ComptimeFloat and candidate_ty.isFloat()) {
90229029 chosen = candidate;
9030 chosen_i = candidate_i + 1;
90239031 continue;
90249032 }
90259033
......@@ -9032,11 +9040,38 @@ fn resolvePeerTypes(
90329040 }
90339041 if (chosen_ty.zigTypeTag() == .EnumLiteral and candidate_ty.zigTypeTag() == .Enum) {
90349042 chosen = candidate;
9043 chosen_i = candidate_i + 1;
90359044 continue;
90369045 }
90379046
9038 // TODO error notes pointing out each type
9039 return sema.mod.fail(&block.base, src, "incompatible types: '{}' and '{}'", .{ chosen_ty, candidate_ty });
9047 // At this point, we hit a compile error. We need to recover
9048 // the source locations.
9049 const chosen_src = candidate_srcs.resolve(
9050 sema.gpa,
9051 block.src_decl,
9052 instructions.len,
9053 chosen_i,
9054 );
9055 const candidate_src = candidate_srcs.resolve(
9056 sema.gpa,
9057 block.src_decl,
9058 instructions.len,
9059 candidate_i + 1,
9060 );
9061
9062 const msg = msg: {
9063 const msg = try sema.mod.errMsg(&block.base, src, "incompatible types: '{}' and '{}'", .{ chosen_ty, candidate_ty });
9064 errdefer msg.destroy(sema.gpa);
9065
9066 if (chosen_src) |src_loc|
9067 try sema.mod.errNote(&block.base, src_loc, msg, "type '{}' here", .{chosen_ty});
9068
9069 if (candidate_src) |src_loc|
9070 try sema.mod.errNote(&block.base, src_loc, msg, "type '{}' here", .{candidate_ty});
9071
9072 break :msg msg;
9073 };
9074 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
90409075 }
90419076
90429077 return sema.typeOf(chosen);
test/cases.zig+10-2
......@@ -288,7 +288,11 @@ pub fn addCases(ctx: *TestContext) !void {
288288 \\pub fn main() void {
289289 \\ _ = @TypeOf(true, 1);
290290 \\}
291 , &[_][]const u8{":2:9: error: incompatible types: 'bool' and 'comptime_int'"});
291 , &[_][]const u8{
292 ":2:9: error: incompatible types: 'bool' and 'comptime_int'",
293 ":2:17: note: type 'bool' here",
294 ":2:23: note: type 'comptime_int' here",
295 });
292296 }
293297
294298 {
......@@ -1729,7 +1733,11 @@ pub fn addCases(ctx: *TestContext) !void {
17291733 \\ const b = false;
17301734 \\ _ = a & &b;
17311735 \\}
1732 , &[_][]const u8{":4:11: error: incompatible types: 'bool' and '*const bool'"});
1736 , &[_][]const u8{
1737 ":4:11: error: incompatible types: 'bool' and '*const bool'",
1738 ":4:9: note: type 'bool' here",
1739 ":4:13: note: type '*const bool' here",
1740 });
17331741
17341742 case.addCompareOutput(
17351743 \\pub fn main() void {