Skip to content

Commit 86de45a

Browse files
committed
Sema: track and emit un-deserialized members
This adds tracking of the vtable holes due to a failure to deserialize vtable entries. This allows for the user to be able to identify what member failed to be deserialied and can aid in understanding why an `open` class may not be subclassed. Future improvements here would allow tracing the XRefPath which failed to be deserialied. However, this still provides an improvement over the existing experience where there is no available information on why the class cannot be inherited from.
1 parent da64dc4 commit 86de45a

File tree

6 files changed

+55
-1
lines changed

6 files changed

+55
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2781,6 +2781,8 @@ ERROR(inheritance_from_class_with_missing_vtable_entries,none,
27812781
"cannot inherit from class %0 because it has overridable members that "
27822782
"could not be loaded",
27832783
(Identifier))
2784+
NOTE(inheritance_from_class_with_missing_vtable_entry, none,
2785+
"could not deserialize %0", (DeclName))
27842786
ERROR(inheritance_from_class_with_missing_vtable_entries_versioned,none,
27852787
"cannot inherit from class %0 (compiled with Swift %1) because it has "
27862788
"overridable members that could not be loaded in Swift %2",

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2553,6 +2553,10 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
25532553
if (!isInvalidSuperclass) {
25542554
CD->diagnose(diag::inheritance_from_class_with_missing_vtable_entries,
25552555
Super->getName());
2556+
for (const auto &member : Super->getMembers())
2557+
if (const auto *MMD = dyn_cast<MissingMemberDecl>(member))
2558+
CD->diagnose(diag::inheritance_from_class_with_missing_vtable_entry,
2559+
MMD->getName());
25562560
isInvalidSuperclass = true;
25572561
}
25582562
}

test/Serialization/Inputs/CLibrary.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
#ifndef CLibrary_h
3+
#define CLibrary_h
4+
5+
typedef struct __attribute__((__objc_bridge__(Object))) CObject *CObjectRef;
6+
7+
#endif
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
module CLibrary {
3+
header "CLibrary.h"
4+
}

test/Serialization/Recovery/typedefs.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,19 @@ public class UserDynamicConvenienceSub: UserDynamicConvenience {
8787
}
8888
_ = UserDynamicConvenienceSub(conveniently: 0)
8989

90-
public class UserSub : User {} // expected-error {{cannot inherit from class 'User' because it has overridable members that could not be loaded}}
90+
public class UserSub : User {}
91+
// expected-error@-1 {{cannot inherit from class 'User' because it has overridable members that could not be loaded}}
92+
// expected-note@-2 {{could not deserialize 'wrappedProp'}}
93+
// expected-note@-3 {{could not deserialize 'returnsWrappedMethod()'}}
94+
// expected-note@-4 {{could not deserialize 'constrainedWrapped'}}
95+
// expected-note@-5 {{could not deserialize 'subscript(_:)'}}
96+
// expected-note@-6 {{could not deserialize 'subscript(_:)'}}
97+
// expected-note@-7 {{could not deserialize 'init(wrapped:)'}}
98+
// expected-note@-8 {{could not deserialize 'init(generic:)'}}
99+
// expected-note@-9 {{could not deserialize 'init(wrappedRequired:)'}}
100+
// expected-note@-10 {{could not deserialize 'init(wrappedRequiredInSub:)'}}
101+
// expected-note@-11 {{could not deserialize 'init(wrappedDynamic:)'}}
102+
// expected-note@-12 {{could not deserialize 'init(wrappedRequiredDynamic:)'}}
91103

92104
#endif // VERIFY
93105

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/swift)
3+
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/swift/SwiftLibrary.swiftmodule %s -module-name SwiftLibrary -I%S/Inputs
4+
// RUN: %target-typecheck-verify-swift -DCLIENT -c %s -module-name client -I%t/swift
5+
6+
#if CLIENT
7+
import SwiftLibrary
8+
9+
public class MyObject: Object {
10+
// expected-error@-1 {{cannot inherit from class 'Object' because it has overridable members that could not be loaded}}
11+
// expected-note@-2 {{could not deserialize 'raw'}}
12+
// expected-note@-3 {{could not deserialize 'init(object:)'}}
13+
}
14+
#else
15+
@_implementationOnly import CLibrary
16+
17+
open class Object {
18+
internal var storage: AnyObject
19+
internal var raw: CObject { unsafeBitCast(storage, to: CObject.self) }
20+
21+
fileprivate init(object: CObject) {
22+
self.storage = object
23+
}
24+
}
25+
#endif

0 commit comments

Comments
 (0)