authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-07-09 20:43:19+08:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-08-04 09:33:12+02:00
log16c11988587ad78cd47ec571e1120c052abd47ed
tree602ffc9c167b22dcab3e6523e3ffb47bc8148dee
parentfcdc5c6b3ccca5cc4e1c2353f280068d1c427153
signaturelock-open Commit is signed but in an unrecognized format.

stage2 Sema: Resolve LazySrcLocs for bitwise and arithmetic exprs


3 files changed, 84 insertions(+), 48 deletions(-)

src/Module.zig+51
......@@ -4268,6 +4268,57 @@ pub const SwitchProngSrc = union(enum) {
42684268 }
42694269};
42704270
4271pub const PeerTypeCandidateSrc = union(enum) {
4272 /// Do not print out error notes for candidate sources
4273 none: void,
4274 /// When we want to know the the src of candidate i, look up at
4275 /// index i in this slice
4276 override: []LazySrcLoc,
4277 /// resolvePeerTypes originates from a @TypeOf(...) call
4278 typeof_builtin_call_node_offset: i32,
4279
4280 pub fn resolve(
4281 self: PeerTypeCandidateSrc,
4282 gpa: *Allocator,
4283 decl: *Decl,
4284 candidates: usize,
4285 candidate_i: usize,
4286 ) ?LazySrcLoc {
4287 @setCold(true);
4288
4289 switch (self) {
4290 .none => {
4291 return null;
4292 },
4293 .override => |candidate_srcs| {
4294 return candidate_srcs[candidate_i];
4295 },
4296 .typeof_builtin_call_node_offset => |node_offset| {
4297 if (candidates <= 2) {
4298 switch (candidate_i) {
4299 0 => return LazySrcLoc{ .node_offset_builtin_call_arg0 = node_offset },
4300 1 => return LazySrcLoc{ .node_offset_builtin_call_arg1 = node_offset },
4301 else => unreachable,
4302 }
4303 }
4304
4305 const tree = decl.namespace.file_scope.getTree(gpa) catch |err| {
4306 // In this case we emit a warning + a less precise source location.
4307 log.warn("unable to load {s}: {s}", .{
4308 decl.namespace.file_scope.sub_file_path, @errorName(err),
4309 });
4310 return LazySrcLoc{ .node_offset = 0 };
4311 };
4312 const node = decl.relativeToNodeIndex(node_offset);
4313 const node_datas = tree.nodes.items(.data);
4314 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
4315
4316 return LazySrcLoc{ .node_abs = params[candidate_i] };
4317 },
4318 }
4319 }
4320};
4321
42714322pub fn analyzeStructFields(mod: *Module, struct_obj: *Struct) CompileError!void {
42724323 const tracy = trace(@src());
42734324 defer tracy.end();
src/Sema.zig+28-47
......@@ -1516,7 +1516,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
15161516
15171517 if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| {
15181518 const peer_inst_list = inferred_alloc.data.stored_inst_list.items;
1519 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, null);
1519 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);
15201520 if (var_is_mut) {
15211521 try sema.validateVarType(block, ty_src, final_elem_ty);
15221522 }
......@@ -2123,7 +2123,7 @@ fn analyzeBlockBody(
21232123 // Need to set the type and emit the Block instruction. This allows machine code generation
21242124 // to emit a jump instruction to after the block when it encounters the break.
21252125 try parent_block.instructions.append(gpa, merges.block_inst);
2126 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, null);
2126 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .none);
21272127 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
21282128 child_block.instructions.items.len);
21292129 sema.air_instructions.items(.data)[merges.block_inst] = .{ .ty_pl = .{
......@@ -4768,7 +4768,7 @@ fn zirBitwise(
47684768 const rhs_ty = sema.typeOf(rhs);
47694769
47704770 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
4771 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, null);
4771 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
47724772 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
47734773 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
47744774
......@@ -4914,7 +4914,7 @@ fn analyzeArithmetic(
49144914 }
49154915
49164916 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
4917 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, null);
4917 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
49184918 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
49194919 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
49204920
......@@ -5223,7 +5223,7 @@ fn analyzeCmp(
52235223 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);
52245224 }
52255225 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
5226 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, null);
5226 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
52275227 if (!resolved_type.isSelfComparable(is_equality_cmp)) {
52285228 return sema.mod.fail(&block.base, src, "{s} operator not allowed for type '{}'", .{
52295229 @tagName(op), resolved_type,
......@@ -5433,7 +5433,7 @@ fn zirTypeofPeer(
54335433 inst_list[i] = sema.resolveInst(arg_ref);
54345434 }
54355435
5436 const result_type = try sema.resolvePeerTypes(block, src, inst_list, extra.data.src_node);
5436 const result_type = try sema.resolvePeerTypes(block, src, inst_list, .{ .typeof_builtin_call_node_offset = extra.data.src_node });
54375437 return sema.addType(result_type);
54385438}
54395439
......@@ -8324,42 +8324,12 @@ fn wrapErrorUnion(
83248324 }
83258325}
83268326
8327fn resolveTypeOfArgSrcLoc(
8328 gpa: *Allocator,
8329 decl: *Decl,
8330 typeof_builtin_call_node_offset: i32,
8331 candidates: usize,
8332 candidate_i: usize,
8333) LazySrcLoc {
8334 @setCold(true);
8335 if (candidates <= 2) {
8336 switch (candidate_i) {
8337 0 => return LazySrcLoc{ .node_offset_builtin_call_arg0 = typeof_builtin_call_node_offset },
8338 1 => return LazySrcLoc{ .node_offset_builtin_call_arg1 = typeof_builtin_call_node_offset },
8339 else => unreachable,
8340 }
8341 }
8342
8343 const tree = decl.namespace.file_scope.getTree(gpa) catch |err| {
8344 // In this case we emit a warning + a less precise source location.
8345 log.warn("unable to load {s}: {s}", .{
8346 decl.namespace.file_scope.sub_file_path, @errorName(err),
8347 });
8348 return LazySrcLoc{ .node_offset = 0 };
8349 };
8350 const node = decl.relativeToNodeIndex(typeof_builtin_call_node_offset);
8351 const node_datas = tree.nodes.items(.data);
8352 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
8353
8354 return LazySrcLoc{ .node_abs = params[candidate_i] };
8355}
8356
83578327fn resolvePeerTypes(
83588328 sema: *Sema,
83598329 block: *Scope.Block,
83608330 src: LazySrcLoc,
83618331 instructions: []Air.Inst.Ref,
8362 typeof_builtin_call_node_offset: ?i32,
8332 candidate_srcs: Module.PeerTypeCandidateSrc,
83638333) !Type {
83648334 if (instructions.len == 0)
83658335 return Type.initTag(.noreturn);
......@@ -8437,20 +8407,31 @@ fn resolvePeerTypes(
84378407 continue;
84388408 }
84398409
8440 // At this point, we hit a compile error. If the call to
8441 // resolvePeerTypes originated from the @TypeOf builtin, we
8442 // need to recover the source locations
8410 // At this point, we hit a compile error. We need to recover
8411 // the source locations.
8412 const chosen_src = candidate_srcs.resolve(
8413 sema.gpa,
8414 block.src_decl,
8415 instructions.len,
8416 chosen_i,
8417 );
8418 const candidate_src = candidate_srcs.resolve(
8419 sema.gpa,
8420 block.src_decl,
8421 instructions.len,
8422 candidate_i + 1,
8423 );
8424
84438425 const msg = msg: {
84448426 const msg = try sema.mod.errMsg(&block.base, src, "incompatible types: '{}' and '{}'", .{ chosen_ty, candidate_ty });
84458427 errdefer msg.destroy(sema.gpa);
8446 // TODO add error notes for other scenarios
8447 if (typeof_builtin_call_node_offset) |node_offset| {
8448 const chosen_src = resolveTypeOfArgSrcLoc(sema.gpa, block.src_decl, node_offset, instructions.len, chosen_i);
8449 const candidate_src = resolveTypeOfArgSrcLoc(sema.gpa, block.src_decl, node_offset, instructions.len, candidate_i + 1);
84508428
8451 try sema.mod.errNote(&block.base, chosen_src, msg, "type '{}' here", .{chosen_ty});
8452 try sema.mod.errNote(&block.base, candidate_src, msg, "type '{}' here", .{candidate_ty});
8453 }
8429 if (chosen_src) |src_loc|
8430 try sema.mod.errNote(&block.base, src_loc, msg, "type '{}' here", .{chosen_ty});
8431
8432 if (candidate_src) |src_loc|
8433 try sema.mod.errNote(&block.base, src_loc, msg, "type '{}' here", .{candidate_ty});
8434
84548435 break :msg msg;
84558436 };
84568437 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
test/cases.zig+5-1
......@@ -1733,7 +1733,11 @@ pub fn addCases(ctx: *TestContext) !void {
17331733 \\ const b = false;
17341734 \\ _ = a & &b;
17351735 \\}
1736 , &[_][]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 });
17371741
17381742 case.addCompareOutput(
17391743 \\pub fn main() void {