authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-06-23 23:52:46+08:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-08-04 09:31:46+02:00
logfcdc5c6b3ccca5cc4e1c2353f280068d1c427153
tree51b10352b916837e2f80f80096f36ee36a5f6c9e
parent0bef271e75657195145a519199ce12b97db246f4
signaturelock-open Commit is signed but in an unrecognized format.

stage2 Sema: Resolve source locations of @TypeOf parameters


2 files changed, 62 insertions(+), 11 deletions(-)

src/Sema.zig+57-10
...@@ -1516,7 +1516,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde...@@ -1516,7 +1516,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
15161516
1517 if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| {1517 if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| {
1518 const peer_inst_list = inferred_alloc.data.stored_inst_list.items;1518 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);1519 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, null);
1520 if (var_is_mut) {1520 if (var_is_mut) {
1521 try sema.validateVarType(block, ty_src, final_elem_ty);1521 try sema.validateVarType(block, ty_src, final_elem_ty);
1522 }1522 }
...@@ -2123,7 +2123,7 @@ fn analyzeBlockBody(...@@ -2123,7 +2123,7 @@ fn analyzeBlockBody(
2123 // Need to set the type and emit the Block instruction. This allows machine code generation2123 // Need to set the type and emit the Block instruction. This allows machine code generation
2124 // to emit a jump instruction to after the block when it encounters the break.2124 // to emit a jump instruction to after the block when it encounters the break.
2125 try parent_block.instructions.append(gpa, merges.block_inst);2125 try parent_block.instructions.append(gpa, merges.block_inst);
2126 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items);2126 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, null);
2127 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +2127 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
2128 child_block.instructions.items.len);2128 child_block.instructions.items.len);
2129 sema.air_instructions.items(.data)[merges.block_inst] = .{ .ty_pl = .{2129 sema.air_instructions.items(.data)[merges.block_inst] = .{ .ty_pl = .{
...@@ -4768,7 +4768,7 @@ fn zirBitwise(...@@ -4768,7 +4768,7 @@ fn zirBitwise(
4768 const rhs_ty = sema.typeOf(rhs);4768 const rhs_ty = sema.typeOf(rhs);
47694769
4770 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };4770 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
4771 const resolved_type = try sema.resolvePeerTypes(block, src, instructions);4771 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, null);
4772 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);4772 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
4773 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);4773 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
47744774
...@@ -4914,7 +4914,7 @@ fn analyzeArithmetic(...@@ -4914,7 +4914,7 @@ fn analyzeArithmetic(
4914 }4914 }
49154915
4916 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };4916 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
4917 const resolved_type = try sema.resolvePeerTypes(block, src, instructions);4917 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, null);
4918 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);4918 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
4919 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);4919 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
49204920
...@@ -5223,7 +5223,7 @@ fn analyzeCmp(...@@ -5223,7 +5223,7 @@ fn analyzeCmp(
5223 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);5223 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);
5224 }5224 }
5225 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };5225 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
5226 const resolved_type = try sema.resolvePeerTypes(block, src, instructions);5226 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, null);
5227 if (!resolved_type.isSelfComparable(is_equality_cmp)) {5227 if (!resolved_type.isSelfComparable(is_equality_cmp)) {
5228 return sema.mod.fail(&block.base, src, "{s} operator not allowed for type '{}'", .{5228 return sema.mod.fail(&block.base, src, "{s} operator not allowed for type '{}'", .{
5229 @tagName(op), resolved_type,5229 @tagName(op), resolved_type,
...@@ -5433,7 +5433,7 @@ fn zirTypeofPeer(...@@ -5433,7 +5433,7 @@ fn zirTypeofPeer(
5433 inst_list[i] = sema.resolveInst(arg_ref);5433 inst_list[i] = sema.resolveInst(arg_ref);
5434 }5434 }
54355435
5436 const result_type = try sema.resolvePeerTypes(block, src, inst_list);5436 const result_type = try sema.resolvePeerTypes(block, src, inst_list, extra.data.src_node);
5437 return sema.addType(result_type);5437 return sema.addType(result_type);
5438}5438}
54395439
...@@ -8324,11 +8324,42 @@ fn wrapErrorUnion(...@@ -8324,11 +8324,42 @@ fn wrapErrorUnion(
8324 }8324 }
8325}8325}
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
8327fn resolvePeerTypes(8357fn resolvePeerTypes(
8328 sema: *Sema,8358 sema: *Sema,
8329 block: *Scope.Block,8359 block: *Scope.Block,
8330 src: LazySrcLoc,8360 src: LazySrcLoc,
8331 instructions: []Air.Inst.Ref,8361 instructions: []Air.Inst.Ref,
8362 typeof_builtin_call_node_offset: ?i32,
8332) !Type {8363) !Type {
8333 if (instructions.len == 0)8364 if (instructions.len == 0)
8334 return Type.initTag(.noreturn);8365 return Type.initTag(.noreturn);
...@@ -8339,7 +8370,8 @@ fn resolvePeerTypes(...@@ -8339,7 +8370,8 @@ fn resolvePeerTypes(
8339 const target = sema.mod.getTarget();8370 const target = sema.mod.getTarget();
83408371
8341 var chosen = instructions[0];8372 var chosen = instructions[0];
8342 for (instructions[1..]) |candidate| {8373 var chosen_i: usize = 0;
8374 for (instructions[1..]) |candidate, candidate_i| {
8343 const candidate_ty = sema.typeOf(candidate);8375 const candidate_ty = sema.typeOf(candidate);
8344 const chosen_ty = sema.typeOf(chosen);8376 const chosen_ty = sema.typeOf(chosen);
8345 if (candidate_ty.eql(chosen_ty))8377 if (candidate_ty.eql(chosen_ty))
...@@ -8348,12 +8380,14 @@ fn resolvePeerTypes(...@@ -8348,12 +8380,14 @@ fn resolvePeerTypes(
8348 continue;8380 continue;
8349 if (chosen_ty.zigTypeTag() == .NoReturn) {8381 if (chosen_ty.zigTypeTag() == .NoReturn) {
8350 chosen = candidate;8382 chosen = candidate;
8383 chosen_i = candidate_i + 1;
8351 continue;8384 continue;
8352 }8385 }
8353 if (candidate_ty.zigTypeTag() == .Undefined)8386 if (candidate_ty.zigTypeTag() == .Undefined)
8354 continue;8387 continue;
8355 if (chosen_ty.zigTypeTag() == .Undefined) {8388 if (chosen_ty.zigTypeTag() == .Undefined) {
8356 chosen = candidate;8389 chosen = candidate;
8390 chosen_i = candidate_i + 1;
8357 continue;8391 continue;
8358 }8392 }
8359 if (chosen_ty.isInt() and8393 if (chosen_ty.isInt() and
...@@ -8362,18 +8396,21 @@ fn resolvePeerTypes(...@@ -8362,18 +8396,21 @@ fn resolvePeerTypes(
8362 {8396 {
8363 if (chosen_ty.intInfo(target).bits < candidate_ty.intInfo(target).bits) {8397 if (chosen_ty.intInfo(target).bits < candidate_ty.intInfo(target).bits) {
8364 chosen = candidate;8398 chosen = candidate;
8399 chosen_i = candidate_i + 1;
8365 }8400 }
8366 continue;8401 continue;
8367 }8402 }
8368 if (chosen_ty.isFloat() and candidate_ty.isFloat()) {8403 if (chosen_ty.isFloat() and candidate_ty.isFloat()) {
8369 if (chosen_ty.floatBits(target) < candidate_ty.floatBits(target)) {8404 if (chosen_ty.floatBits(target) < candidate_ty.floatBits(target)) {
8370 chosen = candidate;8405 chosen = candidate;
8406 chosen_i = candidate_i + 1;
8371 }8407 }
8372 continue;8408 continue;
8373 }8409 }
83748410
8375 if (chosen_ty.zigTypeTag() == .ComptimeInt and candidate_ty.isInt()) {8411 if (chosen_ty.zigTypeTag() == .ComptimeInt and candidate_ty.isInt()) {
8376 chosen = candidate;8412 chosen = candidate;
8413 chosen_i = candidate_i + 1;
8377 continue;8414 continue;
8378 }8415 }
83798416
...@@ -8383,6 +8420,7 @@ fn resolvePeerTypes(...@@ -8383,6 +8420,7 @@ fn resolvePeerTypes(
83838420
8384 if (chosen_ty.zigTypeTag() == .ComptimeFloat and candidate_ty.isFloat()) {8421 if (chosen_ty.zigTypeTag() == .ComptimeFloat and candidate_ty.isFloat()) {
8385 chosen = candidate;8422 chosen = candidate;
8423 chosen_i = candidate_i + 1;
8386 continue;8424 continue;
8387 }8425 }
83888426
...@@ -8395,15 +8433,24 @@ fn resolvePeerTypes(...@@ -8395,15 +8433,24 @@ fn resolvePeerTypes(
8395 }8433 }
8396 if (chosen_ty.zigTypeTag() == .EnumLiteral and candidate_ty.zigTypeTag() == .Enum) {8434 if (chosen_ty.zigTypeTag() == .EnumLiteral and candidate_ty.zigTypeTag() == .Enum) {
8397 chosen = candidate;8435 chosen = candidate;
8436 chosen_i = candidate_i + 1;
8398 continue;8437 continue;
8399 }8438 }
84008439
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
8401 const msg = msg: {8443 const msg = msg: {
8402 const msg = try sema.mod.errMsg(&block.base, src, "incompatible types: '{}' and '{}'", .{ chosen_ty, candidate_ty });8444 const msg = try sema.mod.errMsg(&block.base, src, "incompatible types: '{}' and '{}'", .{ chosen_ty, candidate_ty });
8403 errdefer msg.destroy(sema.gpa);8445 errdefer msg.destroy(sema.gpa);
8404 // TODO add error notes8446 // TODO add error notes for other scenarios
8405 // try sema.mod.errNote(&block.base, chosen.src, msg, "type '{}' here", .{chosen_ty});8447 if (typeof_builtin_call_node_offset) |node_offset| {
8406 // try sema.mod.errNote(&block.base, candidate.src, msg, "type '{}' here", .{candidate_ty});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);
8450
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 }
8407 break :msg msg;8454 break :msg msg;
8408 };8455 };
8409 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);8456 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
test/cases.zig+5-1
...@@ -288,7 +288,11 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -288,7 +288,11 @@ pub fn addCases(ctx: *TestContext) !void {
288 \\pub fn main() void {288 \\pub fn main() void {
289 \\ _ = @TypeOf(true, 1);289 \\ _ = @TypeOf(true, 1);
290 \\}290 \\}
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 });
292 }296 }
293297
294 {298 {