@@ -8521,30 +8521,13 @@ TEST(pipeline_swift_overloads_keep_argument_labels_issue2061) {
85218521
85228522/* Distinct declarations retain their own source ranges and outgoing edges;
85238523 * labels/arity alone cannot choose generic constraints or sync vs async. */
8524- TEST(pipeline_swift_generic_async_identity_issue2061) {
8525- const char *suffixes[] = {"pick<T>(_:T)",
8526- "pick<T:Equatable>(_:T)",
8527- "pick<T;where T:Hashable>(_:T)",
8528- "pick<T;where T:Comparable>(_:T)",
8529- "pick(_:Int)",
8530- "pick(_:Int)async"};
8524+ static int swift_declaration_identity_case(const char **suffixes, int total,
8525+ const char *service_source, const char *caller_source) {
85318526 for (int mode = 0; mode < 2; mode++) {
85328527 char tmp[256];
85338528 snprintf(tmp, sizeof(tmp), "/tmp/cbm_swift_generic_XXXXXX");
85348529 ASSERT_NOT_NULL(cbm_mkdtemp(tmp));
8535- write_temp_file(tmp, "Sources/Service.swift",
8536- "class Service {\n"
8537- "func pick<T>(_ x: T) { mark0() }\n"
8538- "func pick<T: Equatable>(_ x: T) { mark1() }\n"
8539- "func pick<T>(_ x: T) where T: Hashable { mark2() }\n"
8540- "func pick<T>(_ x: T) where T: Comparable { mark3() }\n"
8541- "func pick(_ x: Int) { mark4() }\n"
8542- "func pick(_ x: Int) async { mark5() }\n"
8543- "}\n"
8544- "func mark0() {}\nfunc mark1() {}\nfunc mark2() {}\n"
8545- "func mark3() {}\nfunc mark4() {}\nfunc mark5() {}\n");
8546- const char *caller_source = "class Caller {\nlet service = Service()\n"
8547- "func invoke() { self.service.pick(value) }\n}\n";
8530+ write_temp_file(tmp, "Sources/Service.swift", service_source);
85488531 write_temp_file(tmp, "Sources/Caller.swift", caller_source);
85498532 for (int i = 0; mode && i < 50; i++) {
85508533 char path[64], source[80];
@@ -8561,9 +8544,9 @@ TEST(pipeline_swift_generic_async_identity_issue2061) {
85618544 if (phase) {
85628545 char path[512];
85638546 snprintf(path, sizeof(path), "%s/Sources/Caller.swift", tmp);
8564- write_temp_file(tmp, "Sources/Caller.swift",
8565- "class Caller {\nlet service = Service()\n"
8566- "func invoke() { self.service.pick(value) }\n}\n// changed\n" );
8547+ char changed[1024];
8548+ snprintf(changed, sizeof(changed), "%s// changed\n", caller_source);
8549+ write_temp_file(tmp, "Sources/Caller.swift", changed);
85678550 ASSERT_EQ(pipeline_test_set_mtime(path, 2000000000, 0), 0);
85688551 }
85698552 cbm_pipeline_t *p = cbm_pipeline_new(tmp, db, CBM_MODE_FULL);
@@ -8580,13 +8563,13 @@ TEST(pipeline_swift_generic_async_identity_issue2061) {
85808563 int count = 0;
85818564 ASSERT_EQ(cbm_store_find_nodes_by_name(s, project, "pick", &overloads, &count),
85828565 CBM_STORE_OK);
8583- ASSERT_EQ(count, 6 );
8566+ ASSERT_EQ(count, total );
85848567 cbm_store_free_nodes(overloads, count);
85858568 char qn[512];
85868569 snprintf(qn, sizeof(qn), "%s.Sources.Caller.Caller.invoke()", project);
85878570 cbm_node_t caller = {0};
85888571 ASSERT_EQ(cbm_store_find_node_by_qn(s, project, qn, &caller), CBM_STORE_OK);
8589- for (int i = 0; i < 6 ; i++) {
8572+ for (int i = 0; i < total ; i++) {
85908573 cbm_node_t target = {0}, marker = {0};
85918574 snprintf(qn, sizeof(qn), "%s.Sources.Service.Service.%s", project, suffixes[i]);
85928575 ASSERT_EQ(cbm_store_find_node_by_qn(s, project, qn, &target), CBM_STORE_OK);
@@ -8604,11 +8587,13 @@ TEST(pipeline_swift_generic_async_identity_issue2061) {
86048587 cbm_store_free_edges(edges, n);
86058588 ASSERT_EQ(cbm_store_find_edges_by_source_type(s, caller.id, "CALLS", &edges, &n),
86068589 CBM_STORE_OK);
8607- ASSERT_EQ(n, 6 );
8590+ ASSERT_EQ(n, total );
86088591 int compatible = 0;
86098592 for (int e = 0; e < n; e++) {
86108593 if (edges[e].target_id == target.id) {
8611- ASSERT_NOT_NULL(strstr(edges[e].properties_json, "\"candidates\":6"));
8594+ char candidates[64];
8595+ snprintf(candidates, sizeof(candidates), "\"candidates\":%d", total);
8596+ ASSERT_NOT_NULL(strstr(edges[e].properties_json, candidates));
86128597 compatible++;
86138598 }
86148599 }
@@ -8632,6 +8617,45 @@ TEST(pipeline_swift_generic_async_identity_issue2061) {
86328617 PASS();
86338618}
86348619
8620+ TEST(pipeline_swift_generic_async_identity_issue2061) {
8621+ const char *suffixes[] = {"pick<T>(_:T)", "pick<T:Equatable>(_:T)",
8622+ "pick<T;where T:Hashable>(_:T)",
8623+ "pick<T;where T:Comparable>(_:T)", "pick(_:Int)", "pick(_:Int)async"};
8624+ return swift_declaration_identity_case(
8625+ suffixes, 6,
8626+ "class Service {\n"
8627+ "func pick<T>(_ x: T) { mark0() }\n"
8628+ "func pick<T: Equatable>(_ x: T) { mark1() }\n"
8629+ "func pick<T>(_ x: T) where T: Hashable { mark2() }\n"
8630+ "func pick<T>(_ x: T) where T: Comparable { mark3() }\n"
8631+ "func pick(_ x: Int) { mark4() }\n"
8632+ "func pick(_ x: Int) async { mark5() }\n}\n"
8633+ "func mark0() {}\nfunc mark1() {}\nfunc mark2() {}\n"
8634+ "func mark3() {}\nfunc mark4() {}\nfunc mark5() {}\n",
8635+ "class Caller {\nlet service = Service()\n"
8636+ "func invoke() { self.service.pick(value) }\n}\n");
8637+ }
8638+
8639+ TEST(pipeline_swift_qualified_and_return_identity_issue2061) {
8640+ const char *qualified[] = {"pick(_:A/Item)", "pick(_:B/Item)"};
8641+ ASSERT_EQ(swift_declaration_identity_case(
8642+ qualified, 2,
8643+ "class Service {\nfunc pick(_ x: A.Item) { mark0() }\n"
8644+ "func pick(_ x: B.Item) { mark1() }\n}\n"
8645+ "func mark0() {}\nfunc mark1() {}\n"
8646+ "enum A { struct Item {} }\nenum B { struct Item {} }\n",
8647+ "class Caller {\nlet service = Service()\n"
8648+ "func invoke() { self.service.pick(value) }\n}\n"), 0);
8649+ const char *returns[] = {"pick()=>Int", "pick()=>String"};
8650+ return swift_declaration_identity_case(
8651+ returns, 2,
8652+ "class Service {\nfunc pick() -> Int { mark0(); return 1 }\n"
8653+ "func pick() -> String { mark1(); return \"x\" }\n}\n"
8654+ "func mark0() {}\nfunc mark1() {}\n",
8655+ "class Caller {\nlet service = Service()\n"
8656+ "func invoke() { let _: Int = self.service.pick() }\n}\n");
8657+ }
8658+
86358659/* The parallel call pass must retain both type-only overload candidates. */
86368660TEST(pipeline_swift_overloads_parallel_candidates_issue2061) {
86378661 char tmp[256];
@@ -18469,6 +18493,7 @@ SUITE(pipeline) {
1846918493 RUN_TEST(pipeline_swift_overloads_keep_argument_labels_issue2061);
1847018494 RUN_TEST(pipeline_swift_overloads_parallel_candidates_issue2061);
1847118495 RUN_TEST(pipeline_swift_generic_async_identity_issue2061);
18496+ RUN_TEST(pipeline_swift_qualified_and_return_identity_issue2061);
1847218497 RUN_TEST(pipeline_swift_default_before_required_candidates_issue2061);
1847318498 RUN_TEST(pipeline_swift_incompatible_overload_unresolved_issue2061);
1847418499 RUN_TEST(pipeline_swift_incompatible_overload_parallel_fallback_issue2061);
0 commit comments