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