From 7e4476738687eeb5b052282b21165c3c88de46cf Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Mon, 9 Nov 2026 14:06:06 +0100 Subject: [PATCH 1/3] Unified: Add test coverage for Swift `some` and `any` types Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 89a32053-c825-435d-bc04-d901b469ccfa --- .../tests/corpus/swift/types/any-type.output | 69 ++++++++++++++ .../tests/corpus/swift/types/any-type.swift | 1 + .../tests/corpus/swift/types/some-type.output | 89 +++++++++++++++++++ .../tests/corpus/swift/types/some-type.swift | 3 + 4 files changed, 162 insertions(+) create mode 100644 unified/extractor/tests/corpus/swift/types/any-type.output create mode 100644 unified/extractor/tests/corpus/swift/types/any-type.swift create mode 100644 unified/extractor/tests/corpus/swift/types/some-type.output create mode 100644 unified/extractor/tests/corpus/swift/types/some-type.swift diff --git a/unified/extractor/tests/corpus/swift/types/any-type.output b/unified/extractor/tests/corpus/swift/types/any-type.output new file mode 100644 index 000000000000..09cae58d6688 --- /dev/null +++ b/unified/extractor/tests/corpus/swift/types/any-type.output @@ -0,0 +1,69 @@ +let values: any Collection = [1, 2] + +--- + +sourceFile + endOfFileToken: endOfFile + statements: + codeBlockItem + item: + variableDecl + attributes: + modifiers: + bindingSpecifier: let + bindings: + patternBinding + initializer: + initializerClause + equal: = + value: + arrayExpr + elements: + arrayElement + expression: + integerLiteralExpr + literal: integerLiteral "1" + trailingComma: , + arrayElement + expression: + integerLiteralExpr + literal: integerLiteral "2" + leftSquare: [ + rightSquare: ] + pattern: + identifierPattern + identifier: identifier "values" + typeAnnotation: + typeAnnotation + colon: : + type: + someOrAnyType + constraint: + identifierType + name: identifier "Collection" + genericArgumentClause: + genericArgumentClause + arguments: + genericArgument + argument: + identifierType + name: identifier "Int" + leftAngle: < + rightAngle: > + someOrAnySpecifier: any + +--- + +top_level source="⟨body⟩" + body: + block source="⟨stmt⟩" + stmt: + variable_declaration source="⟨modifier⟩ ⟨pattern⟩: ⟨type⟩ = ⟨value⟩" + modifier: modifier "let" source="let" + pattern: identifier "values" source="values" + type: unsupported_node "any Collection" source="any Collection" + value: + array_literal source="[⟨element⟩, ⟨element⟩]" + element: + int_literal "1" source="1" + int_literal "2" source="2" diff --git a/unified/extractor/tests/corpus/swift/types/any-type.swift b/unified/extractor/tests/corpus/swift/types/any-type.swift new file mode 100644 index 000000000000..c7d08e67311e --- /dev/null +++ b/unified/extractor/tests/corpus/swift/types/any-type.swift @@ -0,0 +1 @@ +let values: any Collection = [1, 2] diff --git a/unified/extractor/tests/corpus/swift/types/some-type.output b/unified/extractor/tests/corpus/swift/types/some-type.output new file mode 100644 index 000000000000..882063a89a0d --- /dev/null +++ b/unified/extractor/tests/corpus/swift/types/some-type.output @@ -0,0 +1,89 @@ +func values(_ input: some Collection) -> some Collection { + input +} + +--- + +sourceFile + endOfFileToken: endOfFile + statements: + codeBlockItem + item: + functionDecl + attributes: + body: + codeBlock + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + declReferenceExpr + baseName: identifier "input" + modifiers: + name: identifier "values" + signature: + functionSignature + parameterClause: + functionParameterClause + leftParen: ( + rightParen: ) + parameters: + functionParameter + colon: : + attributes: + modifiers: + type: + someOrAnyType + constraint: + identifierType + name: identifier "Collection" + genericArgumentClause: + genericArgumentClause + arguments: + genericArgument + argument: + identifierType + name: identifier "Int" + leftAngle: < + rightAngle: > + someOrAnySpecifier: some + firstName: _ + secondName: identifier "input" + returnClause: + returnClause + arrow: -> + type: + someOrAnyType + constraint: + identifierType + name: identifier "Collection" + genericArgumentClause: + genericArgumentClause + arguments: + genericArgument + argument: + identifierType + name: identifier "Int" + leftAngle: < + rightAngle: > + someOrAnySpecifier: some + funcKeyword: func + +--- + +top_level source="⟨body⟩" + body: + block source="⟨stmt⟩" + stmt: + function_declaration source="func ⟨name_node⟩(⟨parameter⟩) -> ⟨return_type⟩ ⟨body⟩" + name_node: identifier "values" source="values" + parameter: + parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" + external_name_node: identifier "_" source="_" + type: unsupported_node "some Collection" source="some Collection" + pattern: identifier "input" source="input" + return_type: unsupported_node "some Collection" source="some Collection" + body: + block source="{\n ⟨stmt⟩\n}" + stmt: identifier "input" source="input" diff --git a/unified/extractor/tests/corpus/swift/types/some-type.swift b/unified/extractor/tests/corpus/swift/types/some-type.swift new file mode 100644 index 000000000000..c54055c4f47b --- /dev/null +++ b/unified/extractor/tests/corpus/swift/types/some-type.swift @@ -0,0 +1,3 @@ +func values(_ input: some Collection) -> some Collection { + input +} From 2abed69b3aafcfd42fde6b1d2f4c90e5a82a7b3b Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Mon, 9 Nov 2026 14:20:40 +0100 Subject: [PATCH 2/3] Unified: Extract Swift `someOrAnyType` as `modified_type_expr` --- unified/extractor/src/languages/swift/swift.rs | 8 +++++++- .../tests/corpus/swift/types/any-type.output | 8 +++++++- .../tests/corpus/swift/types/some-type.output | 16 ++++++++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index af05d93ad172..709b7f51ceb5 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -1198,6 +1198,13 @@ fn translation_rules() -> Vec> { modifier: {late} type: {base}) ), + rule!( + (someOrAnyType someOrAnySpecifier: @@spec constraint: @constraint) + => + (modified_type_expr + modifier: (modifier #{spec}) + type: {constraint}) + ), // Preserve the `super` keyword as a dedicated expression, normally used // as the base of a member access (`super.foo`). rule!((superExpr) => (super_expr)), @@ -1525,7 +1532,6 @@ fn translation_rules() -> Vec> { rule!((postfixIfConfigExpr) => (unsupported_node "")), rule!((poundSourceLocation) => (unsupported_node "")), rule!((precedenceGroupDecl) => (unsupported_node "")), - rule!((someOrAnyType) => (unsupported_node "")), rule!((subscriptDecl) => (unsupported_node "")), rule!((suppressedType) => (unsupported_node "")), rule!((typeExpr) => (unsupported_node "")), diff --git a/unified/extractor/tests/corpus/swift/types/any-type.output b/unified/extractor/tests/corpus/swift/types/any-type.output index 09cae58d6688..92862f73c715 100644 --- a/unified/extractor/tests/corpus/swift/types/any-type.output +++ b/unified/extractor/tests/corpus/swift/types/any-type.output @@ -61,7 +61,13 @@ top_level source="⟨body⟩" variable_declaration source="⟨modifier⟩ ⟨pattern⟩: ⟨type⟩ = ⟨value⟩" modifier: modifier "let" source="let" pattern: identifier "values" source="values" - type: unsupported_node "any Collection" source="any Collection" + type: + modified_type_expr source="⟨modifier⟩ ⟨type⟩" + modifier: modifier "any" source="any" + type: + generic_type_expr source="⟨base⟩<⟨type_argument⟩>" + base: identifier "Collection" source="Collection" + type_argument: identifier "Int" source="Int" value: array_literal source="[⟨element⟩, ⟨element⟩]" element: diff --git a/unified/extractor/tests/corpus/swift/types/some-type.output b/unified/extractor/tests/corpus/swift/types/some-type.output index 882063a89a0d..5161bc40643a 100644 --- a/unified/extractor/tests/corpus/swift/types/some-type.output +++ b/unified/extractor/tests/corpus/swift/types/some-type.output @@ -81,9 +81,21 @@ top_level source="⟨body⟩" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" external_name_node: identifier "_" source="_" - type: unsupported_node "some Collection" source="some Collection" + type: + modified_type_expr source="⟨modifier⟩ ⟨type⟩" + modifier: modifier "some" source="some" + type: + generic_type_expr source="⟨base⟩<⟨type_argument⟩>" + base: identifier "Collection" source="Collection" + type_argument: identifier "Int" source="Int" pattern: identifier "input" source="input" - return_type: unsupported_node "some Collection" source="some Collection" + return_type: + modified_type_expr source="⟨modifier⟩ ⟨type⟩" + modifier: modifier "some" source="some" + type: + generic_type_expr source="⟨base⟩<⟨type_argument⟩>" + base: identifier "Collection" source="Collection" + type_argument: identifier "Int" source="Int" body: block source="{\n ⟨stmt⟩\n}" stmt: identifier "input" source="input" From aed398a016878b0d7b47c32d2fa5c06dfcc80101 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Tue, 10 Nov 2026 12:51:27 +0100 Subject: [PATCH 3/3] Unified: Accept changes to tests and expected files --- unified/ql/test/library-tests/type-inference/generics.swift | 2 +- .../test/library-tests/type-inference/type-inference.expected | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/unified/ql/test/library-tests/type-inference/generics.swift b/unified/ql/test/library-tests/type-inference/generics.swift index 99269646e864..a2e050c790e2 100644 --- a/unified/ql/test/library-tests/type-inference/generics.swift +++ b/unified/ql/test/library-tests/type-inference/generics.swift @@ -309,7 +309,7 @@ struct IntPrimaryAssociatedType: PrimaryAssociatedTypeProtocol { } func getPrimaryAssociatedType(_ value: some PrimaryAssociatedTypeProtocol) -> Int { - return value.element() // $ MISSING: target=PrimaryAssociatedTypeProtocol.element + return value.element() // $ target=PrimaryAssociatedTypeProtocol.element } func testPrimaryAssociatedType() { diff --git a/unified/ql/test/library-tests/type-inference/type-inference.expected b/unified/ql/test/library-tests/type-inference/type-inference.expected index 4a87e1942d3b..c6552ced30ed 100644 --- a/unified/ql/test/library-tests/type-inference/type-inference.expected +++ b/unified/ql/test/library-tests/type-inference/type-inference.expected @@ -351,6 +351,8 @@ inferCertainType | generics.swift:253:10:253:10 | c | | generics.swift:252:14:252:27 | T | | generics.swift:287:65:287:69 | value | | generics.swift:287:33:287:60 | T | | generics.swift:288:10:288:14 | value | | generics.swift:287:33:287:60 | T | +| generics.swift:311:33:311:37 | value | | generics.swift:297:1:301:1 | PrimaryAssociatedTypeProtocol | +| generics.swift:312:10:312:14 | value | | generics.swift:297:1:301:1 | PrimaryAssociatedTypeProtocol | | key_paths.swift:4:7:4:7 | x | | {EXTERNAL LOCATION} | Double | | key_paths.swift:5:7:5:7 | y | | {EXTERNAL LOCATION} | Double | | key_paths.swift:7:8:7:8 | x | | {EXTERNAL LOCATION} | Double | @@ -2041,6 +2043,8 @@ inferType | generics.swift:292:42:292:63 | StringAssociatedType(...) | | generics.swift:275:1:285:1 | StringAssociatedType | | generics.swift:306:25:308:3 | Block | | {EXTERNAL LOCATION} | Int | | generics.swift:307:12:307:13 | 42 | | {EXTERNAL LOCATION} | Int | +| generics.swift:311:33:311:37 | value | | generics.swift:297:1:301:1 | PrimaryAssociatedTypeProtocol | +| generics.swift:312:10:312:14 | value | | generics.swift:297:1:301:1 | PrimaryAssociatedTypeProtocol | | generics.swift:316:7:316:11 | value | | {EXTERNAL LOCATION} | Int | | generics.swift:316:15:316:66 | getPrimaryAssociatedType(...) | | {EXTERNAL LOCATION} | Int | | generics.swift:316:40:316:63 | IntPrimaryAssociatedType | | generics.swift:303:1:309:1 | IntPrimaryAssociatedType |