Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiating class metadata for class with missing weak-linked ancestor

When I run my app with Xcode 12.5 and Swift 5.4. I get a crash in pre-main:

instantiating class metadata for class with missing weak-linked ancestor

The same code runs on Xcode 12.4 and Swift 5.3 with no issues

like image 345
Luca Bartoletti Avatar asked May 28 '21 16:05

Luca Bartoletti


Video Answer


1 Answers

instantiating class metadata for class with missing weak-linked ancestor

Reading the message it seems to suggest that while loading the class metadata at startup ("instantiating class metadata") the runtime couldn't find the associated superclass ("class with missing weak-linked ancestor")

This seems to be confirmed by the Swift codebase. As the error message comes from this function in the Swift runtime:

static ClassMetadataBounds
computeMetadataBoundsForSuperclass(const void *ref,
                                   TypeReferenceKind refKind) {
  switch (refKind) {
    case TypeReferenceKind::IndirectTypeDescriptor: {
    auto description = *reinterpret_cast<const ClassDescriptor * const __ptrauth_swift_type_descriptor *>(ref);
    if (!description) {
      swift::fatalError(0, "instantiating class metadata for class with "
                         "missing weak-linked ancestor");
    }
    return description->getMetadataBounds();
  }
}

that is called from:

// Compute the bounds for the superclass, extending it to the minimum
// bounds of a Swift class.
if (const void *superRef = description->getResilientSuperclass()) {
  bounds = computeMetadataBoundsForSuperclass(superRef,
                         description->getResilientSuperclassReferenceKind());
} else {
  bounds = ClassMetadataBounds::forSwiftRootClass();
}

this is where the runtime is looking for the superclass of the class it's loading.

After some digging, it turns out that while on Swift 5.3 you where allowed to have

@available(iOS 13.0, *)
class A {
   class B: HostingView<MyView> {
   }
}

and both A and A.B would been ignored in iOS 12. In Swift 5.4 (not sure if a change or a bug) A is ignored but A.B is loaded.

So you can solve the crash with:

@available(iOS 13.0, *)
class A {
   @available(iOS 13.0, *)
   class B: HostingView<MyView> {
   }
}
like image 105
Saul Avatar answered Oct 21 '22 11:10

Saul