Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Off-by-one bug in generic inherited type. #658

Open
MatyasKriz opened this issue Jun 28, 2020 · 2 comments
Open

Off-by-one bug in generic inherited type. #658

MatyasKriz opened this issue Jun 28, 2020 · 2 comments

Comments

@MatyasKriz
Copy link

MatyasKriz commented Jun 28, 2020

Hey, I'm maintaining Cuckoo and recently a bug surfaced (though it was present all this time, just under our radar) where SourceKitten includes the last > of the generic inherited type.

I've been using SourceKitten 0.23.2 until now; though upgrading to 0.29.0 didn't help, unfortunately.

Xcode 11.5, though it's the same result on 10.2.1.

Some examples:

struct gg<G: T<Int>> {}  // "key.inheritedTypes" is "T<Int>>"
func bg<T: G<Void>>()    // "key.inheritedTypes" is "G<Void>>"

This applies for any class, struct, or function.

I've tried tracking this bug down inside the project (master) with the intention of filing a PR, though the source code gets increasingly complex for my iOS brain. I found that at Request.swift:88, the string is already incorrect and I'm unsure whether it's a SourceKitten bug or SourceKit provides incorrect numbers.

I've created a general structure test that should go green when this is resolved:

func testGenericInheritedType() throws {
        let structure = try Structure(file: File(contents: "class Foo<T, U: V<T>> {}"))
        let expected: NSDictionary = [
            "key.substructure": [
                [
                    "key.kind": "source.lang.swift.decl.class",
                    "key.accessibility": "source.lang.swift.accessibility.internal",
                    "key.offset": 0,
                    "key.nameoffset": 6,
                    "key.namelength": 3,
                    "key.bodyoffset": 23,
                    "key.bodylength": 0,
                    "key.length": 24,
                    "key.name": "Foo",
                    "key.substructure": [
                        [
                            "key.kind": "source.lang.swift.decl.generic_type_param",
                            "key.length": 1,
                            "key.name": "T",
                            "key.namelength": 1,
                            "key.nameoffset": 10,
                            "key.offset": 10,
                        ],
                        [
                            "key.elements": [
                                [
                                    "key.kind": "source.lang.swift.structure.elem.typeref",
                                    "key.length": 4,
                                    "key.offset": 16,
                                ]
                            ],
                            "key.inheritedtypes": [
                                [
                                    "key.name": "V<T>",
                                ]
                            ],
                            "key.kind": "source.lang.swift.decl.generic_type_param",
                            "key.length": 7,
                            "key.name": "U",
                            "key.namelength": 1,
                            "key.nameoffset": 13,
                            "key.offset": 13,
                      ]
                    ]
                ]
            ],
            "key.offset": 0,
            "key.diagnostic_stage": "source.diagnostic.stage.swift.parse",
            "key.length": 24,
        ]
        XCTAssertEqual(toNSDictionary(structure.dictionary), expected, "should generate expected structure")
    }

Though I'm not sure about the specific offsets, so I wouldn't trust me on this.

In Cuckoo I added some simple protection against this, but it's pretty fragile (it just checks for >> in the last parameter), so I wanted to get your feedback on the complexity of this issue and whether we should rather compensate on our side rather than waiting for a fix.

Oh and I tried looking for this issue, so forgive me if I overlooked a duplicate, feel free to close this if it's known and/or unfixable. If I forgot to disclose some important info, let me know! 🙂

One last thing, this bug can be sidestepped by adding a space in front of the last >. So <T: G<Void> > actually returns the correct inherited type of just G<Void>.

EDIT: One actually important thing might be, this issue only arises when the inheritance type is generic as well, for example <T: G> correctly returns just G as the inherited type.

@johnfairh
Copy link
Collaborator

This is a Swift bug, it's wrong coming out of SourceKit. Latest swift/master:

; cat Test.swift
struct gg<G: T<Int>> {}
; sourcekitd-test -req structure Test.swift 
{
  key.request: source.request.configuration.global,
  key.optimize_for_ide: 1
}
{
  key.request: source.request.editor.open,
  key.name: "/Users/johnf/project/SourceKit/Test.swift",
  key.sourcefile: "/Users/johnf/project/SourceKit/Test.swift",
  key.enablesyntaxmap: 0,
  key.syntaxtreetransfermode: source.syntaxtree.transfer.off,
  key.enablesubstructure: 1,
  key.syntactic_only: 1
}
{
  key.offset: 0,
  key.length: 24,
  key.diagnostic_stage: source.diagnostic.stage.swift.parse,
  key.substructure: [
    {
      key.kind: source.lang.swift.decl.struct,
      key.accessibility: source.lang.swift.accessibility.internal,
      key.name: "gg",
      key.offset: 0,
      key.length: 23,
      key.nameoffset: 7,
      key.namelength: 2,
      key.bodyoffset: 22,
      key.bodylength: 0,
      key.substructure: [
        {
          key.kind: source.lang.swift.decl.generic_type_param,
          key.name: "G",
          key.offset: 10,
          key.length: 10,
          key.nameoffset: 10,
          key.namelength: 1,
          key.inheritedtypes: [
            {
              key.name: "T<Int>>"
            }
          ],
...

You could open it on https://bugs.swift.org ?

@MatyasKriz
Copy link
Author

Thanks for the tip, I haven't had the chance to file a Swift bug issue before, so the link was very helpful.

The issue in question is here: https://bugs.swift.org/browse/SR-13115

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants