XC8: Linker crashes at sorted(by:) on casted array (from CoreData)

Hello,


I'm battling with a real frustrating error when archiving my project. All works well when building or running to a device or simulator, while archiving however I get this error:


Undefined symbols for architecture arm64:
  "Swift.UnsafeMutableBufferPointer.(subscript.materializeForSet : (Swift.Int) -> A).(closure #1)", referenced from:
      function signature specialization <Arg[2] = Exploded> of generic specialization <Swift.UnsafeMutableBufferPointer<Library.Thing> with Swift.UnsafeMutableBufferPointer<Library.Thing> : Swift.MutableCollection in Swift and Swift.UnsafeMutableBufferPointer<Library.Thing> : Swift.RandomAccessCollection in Swift> of Swift._siftDown <A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection> (inout A, index : A.Index, subRange : Swift.Range<A.Index>, by : inout (A.Iterator.Element, A.Iterator.Element) -> Swift.Bool) -> () in Manager
      function signature specialization <Arg[1] = Exploded> of generic specialization <Swift.UnsafeMutableBufferPointer<Library.Thing> with Swift.UnsafeMutableBufferPointer<Library.Thing> : Swift.MutableCollection in Swift and Swift.UnsafeMutableBufferPointer<Library.Thing> : Swift.RandomAccessCollection in Swift> of Swift._heapSort <A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection> (inout A, subRange : Swift.Range<A.Index>, by : inout (A.Iterator.Element, A.Iterator.Element) -> Swift.Bool) -> () in Manager
      function signature specialization <Arg[1] = Exploded> of generic specialization <Swift.UnsafeMutableBufferPointer<Library.Thing> with Swift.UnsafeMutableBufferPointer<Library.Thing> : Swift.MutableCollection in Swift and Swift.UnsafeMutableBufferPointer<Library.Thing> : Swift.RandomAccessCollection in Swift> of Swift._partition <A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection> (inout A, subRange : Swift.Range<A.Index>, by : inout (A.Iterator.Element, A.Iterator.Element) -> Swift.Bool) -> A.Index in Manager
      function signature specialization <Arg[2] = Exploded> of generic specialization <Swift.UnsafeMutableBufferPointer<Swift.String> with Swift.UnsafeMutableBufferPointer<Swift.String> : Swift.MutableCollection in Swift and Swift.UnsafeMutableBufferPointer<Swift.String> : Swift.RandomAccessCollection in Swift> of Swift._siftDown <A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection> (inout A, index : A.Index, subRange : Swift.Range<A.Index>, by : inout (A.Iterator.Element, A.Iterator.Element) -> Swift.Bool) -> () in Manager
      function signature specialization <Arg[1] = Exploded> of generic specialization <Swift.UnsafeMutableBufferPointer<Swift.String> with Swift.UnsafeMutableBufferPointer<Swift.String> : Swift.MutableCollection in Swift and Swift.UnsafeMutableBufferPointer<Swift.String> : Swift.RandomAccessCollection in Swift> of Swift._heapSort <A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection> (inout A, subRange : Swift.Range<A.Index>, by : inout (A.Iterator.Element, A.Iterator.Element) -> Swift.Bool) -> () in Manager
      function signature specialization <Arg[1] = Exploded> of generic specialization <Swift.UnsafeMutableBufferPointer<Swift.String> with Swift.UnsafeMutableBufferPointer<Swift.String> : Swift.MutableCollection in Swift and Swift.UnsafeMutableBufferPointer<Swift.String> : Swift.RandomAccessCollection in Swift> of Swift._partition <A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection> (inout A, subRange : Swift.Range<A.Index>, by : inout (A.Iterator.Element, A.Iterator.Element) -> Swift.Bool) -> A.Index in Manager
ld: symbol(s) not found for architecture arm64


The relevant part looks a bit like this:


let meta:MetaData?
if let context = context {
    meta = MetaData.mr_findFirst(in: context)
} else {
    meta = MetaData.mr_findFirst()
}
if let things = meta?.availableThings?.allObjects as? [Thing] {
    return things.sorted(by: { (a, b) -> Bool in
        return true
    })
}


The cast is there to make things a bit more obvious - the Set<Thing> is casted to [Thing], but sorted(by:) crashes the linker. A more direct approach (sorting on the Set etc) causes the same issues. Maybe NSSortDescriptor can help me work around it for now?


Can anyone help? Thanks!

Replies

It's a bug in the compiler or the linker. (My bug # for this is 28294466.) In my case, I couldn't find a direct workaround.


The array elements were of a type defined in an embedded framework. The only indirect workaround I found was to add a method to the framework that returned a sorted array. In other words, it worked if the sorted element type didn't cross a module boundary while being sorted (kinda).


In your example, this would look something like:


if let things = meta?.availableThings?.allSortedObjects …


and the new method "allSortedObjects" would return something like:


     return allObjects.sorted …

Oh I see, that makes sense, thanks!

It's the same bug then, because my Thing is in a dynamic framework (Library.Thing).

For now, a colleague managed to work around this by casting the Array to an NSArray and sorting it with a linq extension (https://github.com/ColinEberhardt/LinqToObjectiveC).

Let's hope this gets fixed soon 🙂

I found a simple workaround.


In the library:


extension Thing {
     static func sorted(array: [Thing]) -> [Thing] { 
          return array.sorted { $0 < $1 }        
     }      
}


In the app:


let sortedThings = Thing.sorted(array: things)


Note that a Collection extension will not work.

I was having this issue when my function that sorted was a method on the class being sorted. I move the sort method to another file and then it worked.

I have the same error.

> Symbol: Swift.UnsafeMutableBufferPointer.(subscript.materializeForSet : (Swift.Int) -> A).(closure #1)
> Referenced from: function signature specialization <Arg[2] = Exploded> of generic specialization <Swift.UnsafeMutableBufferPointer<Teleport.Shop> with Swift.UnsafeMutableBufferPointer<Teleport.Shop> : Swift.MutableCollection in Swift and Swift.UnsafeMutableBufferPointer<Teleport.Shop> : Swift.RandomAccessCollection in Swift> of Swift._siftDown <A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection> (inout A, index : A.Index, subRange : Swift.Range<A.Index>, by : inout (A.Iterator.Element, A.Iterator.Element) -> Swift.Bool) -> () in ShopsVM.o

when I try

self.shops.value = self.allItems.sorted(by: { $0.id < $1.id })

😟

Turning off Whole Module Optimization worked for me.