Off-by-one bug in generic inherited type.
Nobody has claimed this yet.
- Dominant language
- Swift
- Stars
- 2.4k
- Forks
- 237
- PR merge metrics
- No merged PRs in 30d
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at Request.swift:88, where the issue reports that the inherited type is already incorrect, and inspect the supplied Structure test for the expected key.inheritedtypes value. Compare behavior for generic and non-generic inherited types, including the spacing workaround. Done means generic inherited types no longer include the final extra > while the provided test passes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100