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-3328] Cannot extend PHFetchResult to conform to Sequence in Swift 3 #45916

Closed
an0 mannequin opened this issue Dec 4, 2016 · 11 comments
Closed

[SR-3328] Cannot extend PHFetchResult to conform to Sequence in Swift 3 #45916

an0 mannequin opened this issue Dec 4, 2016 · 11 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@an0
Copy link
Mannequin

an0 mannequin commented Dec 4, 2016

Previous ID SR-3328
Radar rdar://problem/29982080
Original Reporter @an0
Type Bug
Status Resolved
Resolution Duplicate
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee @an0
Priority Medium

md5: cf208174c2cc5e5b041dd6cefebc53cb

relates to:

  • SR-1576 Swift 3 can't subscript PHFetchResult
  • SR-2708 Extending ObjC generics in Swift 3 does not compile

Issue Description:

extension PHFetchResult: Sequence {
    public func makeIterator() -> NSFastEnumerationIterator {
        return NSFastEnumerationIterator(self)
    }
}

This used to work in Swift 2 but now in Swift 3 reports this error:
Extension of a generic Objective-C class cannot access the class's generic parameters at runtime.

I know it is due to current limitation of the language but is there any temporary workaround?

@mattneub
Copy link

mattneub commented Dec 5, 2016

Anticipated by https://bugs.swift.org/browse/SR-1576

@belkadan
Copy link
Contributor

belkadan commented Dec 5, 2016

A not-so-pretty workaround: use a wrapper type.

import Photos

struct ResultSequence<Element: AnyObject>: Sequence {
  var result: PHFetchResult<Element>
  init(_ result: PHFetchResult<Element>) {
    self.result = result
  }
  func makeIterator() -> NSFastEnumerationIterator {
    return NSFastEnumerationIterator(self.result)
  }
}


func test(_ request: PHFetchResult<PHCollection>) {
  for elem in ResultSequence(request) {
    print(elem)
  }
}

@an0
Copy link
Mannequin Author

an0 mannequin commented Dec 5, 2016

@belkadan thanks!

@jckarter
Copy link
Member

jckarter commented Dec 5, 2016

Yes, this is the same problem as SR-1576. Conforming with AnyObject as your element type should work too.

@an0
Copy link
Mannequin Author

an0 mannequin commented Dec 5, 2016

@jckarter Does it depend on https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md being implemented? If so, not usable currently.

@jckarter
Copy link
Member

jckarter commented Dec 5, 2016

No, just unconditionally use `typealias Element = AnyObject` and force-cast to PHFetchResult<AnyObject>.

@an0
Copy link
Mannequin Author

an0 mannequin commented Dec 5, 2016

@jckarter I'm lost. Where to put `typealias Element = AnyObject`? `Sequence` doesn't have the associated type `Element`.

@jckarter
Copy link
Member

jckarter commented Dec 5, 2016

I meant something like this:

import Photos

extension PHFetchResult: Sequence {
    public func makeIterator() -> FetchResultIterator {
        return FetchResultIterator(self as! PHFetchResult<AnyObject>)
    }
}

@objc public class FetchResultIterator: NSObject, IteratorProtocol {
  // iterator implementation here
}

Extensions of ObjC generic classes are limited to being @objc-compatible, so you need to use an iterator class that's @objc. NSFastEnumeratorIterator is not ObjC-representable.

@an0
Copy link
Mannequin Author

an0 mannequin commented Dec 5, 2016

@jckarter Thanks! It's a better workaround because only the extension implementation needs patches.

@swift-ci
Copy link
Collaborator

Comment by Marc Knaup (JIRA)

The following code works fine in release mode but crashes at runtime in debug mode in some cases (e.g. when calling .map() on the sequence) 🙁

extension NSFastEnumeration {

    public func makeIterator() -> NSFastEnumerationIterator {
        return NSFastEnumerationIterator(self)
    }
}

extension PHFetchResult: Sequence {}

Looks like that no matter how you make PHFetchResult conform to Sequence, it will randomly crash at runtime in debug mode - also with @jckarter's suggestion.

@jckarter
Copy link
Member

@swift-ci create

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
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
Projects
None yet
Development

No branches or pull requests

4 participants