[Serialization] Recover from failures in ModuleFile::lookupClassMembers

Access to a missing member on an AnyObject triggers a typo correction
that looks at all class members in imported modules. Make sure it
recovers from deserializing members referencing implementation-only
imported types.

rdar://79427805
This commit is contained in:
Alexis Laferrière
2021-06-22 18:16:03 -07:00
parent b4c873aa55
commit 4f0c57a2d3
2 changed files with 33 additions and 5 deletions

View File

@@ -794,7 +794,13 @@ void ModuleFile::lookupClassMembers(ImportPath::Access accessPath,
if (!accessPath.empty()) { if (!accessPath.empty()) {
for (const auto &list : Core->ClassMembersForDynamicLookup->data()) { for (const auto &list : Core->ClassMembersForDynamicLookup->data()) {
for (auto item : list) { for (auto item : list) {
auto vd = cast<ValueDecl>(getDecl(item.second)); auto decl = getDeclChecked(item.second);
if (!decl) {
llvm::consumeError(decl.takeError());
continue;
}
auto vd = cast<ValueDecl>(decl.get());
auto dc = vd->getDeclContext(); auto dc = vd->getDeclContext();
while (!dc->getParent()->isModuleScopeContext()) while (!dc->getParent()->isModuleScopeContext())
dc = dc->getParent(); dc = dc->getParent();
@@ -808,10 +814,17 @@ void ModuleFile::lookupClassMembers(ImportPath::Access accessPath,
} }
for (const auto &list : Core->ClassMembersForDynamicLookup->data()) { for (const auto &list : Core->ClassMembersForDynamicLookup->data()) {
for (auto item : list) for (auto item : list) {
consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)), auto decl = getDeclChecked(item.second);
if (!decl) {
llvm::consumeError(decl.takeError());
continue;
}
consumer.foundDecl(cast<ValueDecl>(decl.get()),
DeclVisibilityKind::DynamicLookup, DeclVisibilityKind::DynamicLookup,
DynamicLookupInfo::AnyObject); DynamicLookupInfo::AnyObject);
}
} }
} }

View File

@@ -12,8 +12,9 @@
//// The client app should build OK without the private module. Removing the //// The client app should build OK without the private module. Removing the
//// private module is superfluous but makes sure that it's not somehow loaded. //// private module is superfluous but makes sure that it's not somehow loaded.
// RUN: rm %t/private_lib.swiftmodule // RUN: rm %t/private_lib.swiftmodule
// RUN: %target-swift-frontend -typecheck -DCLIENT_APP -primary-file %s -I %t -index-system-modules -index-store-path %t // RUN: %target-swift-frontend -typecheck -DCLIENT_APP %s -I %t -index-system-modules -index-store-path %t
// RUN: %target-swift-frontend -emit-sil -DCLIENT_APP -primary-file %s -I %t -module-name client // RUN: %target-swift-frontend -typecheck -DCLIENT_APP %s -I %t -D FAIL_TYPECHECK -verify
// RUN: %target-swift-frontend -emit-sil -DCLIENT_APP %s -I %t -module-name client
//// Printing the public module should not crash when checking for overrides of //// Printing the public module should not crash when checking for overrides of
//// methods from the private module. //// methods from the private module.
@@ -46,6 +47,8 @@ public protocol HiddenProtocolWithOverride {
func hiddenOverride() func hiddenOverride()
} }
public class HiddenClass {}
#elseif PUBLIC_LIB #elseif PUBLIC_LIB
@_implementationOnly import private_lib @_implementationOnly import private_lib
@@ -91,6 +94,10 @@ public struct PublicStructConformsToHiddenProtocol: RefinesHiddenProtocol {
public init() { } public init() { }
} }
public class SomeClass {
func funcUsingIoiType(_ a: HiddenClass) {}
}
#elseif CLIENT_APP #elseif CLIENT_APP
import public_lib import public_lib
@@ -101,4 +108,12 @@ print(s.nonWrappedVar)
var p = PublicStructConformsToHiddenProtocol() var p = PublicStructConformsToHiddenProtocol()
print(p) print(p)
#if FAIL_TYPECHECK
// Access to a missing member on an AnyObject triggers a typo correction
// that looks at *all* class members. rdar://79427805
class ClassUnrelatedToSomeClass {}
var something = ClassUnrelatedToSomeClass() as AnyObject
something.triggerTypoCorrection = 123 // expected-error {{value of type 'AnyObject' has no member 'triggerTypoCorrection'}}
#endif
#endif #endif