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

[SR-11529] Xcode won't ever build the project nor finish indexing it when keyPath subscript overlaps with others. #53930

Open
swift-ci opened this issue Sep 26, 2019 · 1 comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself key paths Feature: key paths (both native and Objective-C)

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-11529
Radar rdar://problem/55746272
Original Reporter sunshinejr (JIRA User)
Type Bug
Environment

macOS: Catalina beta 9, but I also had reports of these in mojave
Xcode: 11 but I tried 10.3 and it failed as well
Swift: only used bundled toolchains on given Xcode's, nothing fancy

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, KeyPaths
Assignee None
Priority Medium

md5: f131fa5fa4bfd8b3a7a76bfb7bceaf57

Issue Description:

So I was debugging this issue my whole day and it's really weird as my current workaround doesn't make sense to me so please bear with me. Finally I was able to recreate a small code sample that breaks both the indexer and compiler❓.

Given the code below (either in another module/package or free floating in a file)

public var CrashDefaults = SwiftCrashDefaults(keys: SwiftCrashDefaultsKeys(key: .init(bar: "")))

public protocol Base {
    associatedtype T
}

extension String: Base {
    public typealias T = String
}

extension Optional: Base where Wrapped: Base {
    public typealias T = Self
}

public struct SwiftCrashDefaultsKey<T: Base> {
    public let bar: T

    public init(bar: T) { self.bar = bar; }
}

public protocol SwiftCrashDefaultsKeyStore {}

public struct SwiftCrashDefaultsKeys: SwiftCrashDefaultsKeyStore {

    public let key: SwiftCrashDefaultsKey<String?>

    public init(key: SwiftCrashDefaultsKey<String?>) { self.key = key}
}

public struct SwiftCrashDefaults<KeyStore: SwiftCrashDefaultsKeyStore> {

    public let keys: KeyStore

    public init(keys: KeyStore) {
        self.keys = keys
    }

    public subscript<T: Base>(key: SwiftCrashDefaultsKey<T>) -> T.T {
        get { return 1 as! T.T }
        set {}
    }

    public subscript<T: Base>(keyPath: KeyPath<KeyStore, SwiftCrashDefaultsKey<T>>) -> T.T {
        get { return 1 as! T.T }
        set {}
    }
}

you are able to use it and assign it:

let compilerWontCrash = CrashDefaults[\.key]

but you are not able to use it in a conditional statement as it will result in an infinite indexing and never-ending build process:

if let compilerCrash = CrashDefaults[\.key]{
    NSLog("it should just log it but it won't :( \(compilerCrash)")
}

Workarounds

  1. Don't use a global variable
    E.g. when you specify your local `crashDefaults` variable you will be able to use it in the conditional statement:

    let crashDefaults = SwiftCrashDefaults(keys: SwiftCrashDefaultsKeys(key: .init(bar: "foo")))
    if let compilerCrash = crashDefaults[\.key]{
        NSLog("it should just log it and it will! \(compilerCrash)")
    }
  2. Add a label to your other subscript
    So instead of having this:

    public subscript<T: Base>(key: SwiftCrashDefaultsKey<T>) -> T.T {
        get { return 1 as! T.T }
        set {}
    }

    Use this:

    public subscript<T: Base>(key key: SwiftCrashDefaultsKey<T>) -> T.T {
        get { return 1 as! T.T }
        set {}
    }

    and it will also build as expected.

@belkadan
Copy link
Contributor

@swift-ci create

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself key paths Feature: key paths (both native and Objective-C)
Projects
None yet
Development

No branches or pull requests

2 participants