mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
ClangImporter: Find type witnesses in finishNormalConformance()
This commit is contained in:
@@ -359,84 +359,6 @@ bool NormalProtocolConformance::hasTypeWitness(AssociatedTypeDecl *assocType,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Directly resolve type witnesses that are known to the compiler because they
|
|
||||||
/// were synthesized by the compiler.
|
|
||||||
///
|
|
||||||
/// FIXME: This is a hack to work around the fact that we don't have a
|
|
||||||
/// TypeChecker when we need one.
|
|
||||||
///
|
|
||||||
/// \returns true if we resolved the type witness.
|
|
||||||
static bool resolveKnownTypeWitness(NormalProtocolConformance *conformance,
|
|
||||||
AssociatedTypeDecl *assocType) {
|
|
||||||
auto nominal = conformance->getType()->getAnyNominal();
|
|
||||||
if (!nominal) return false;
|
|
||||||
|
|
||||||
if (!nominal->hasClangNode()) return false;
|
|
||||||
|
|
||||||
auto proto = conformance->getProtocol();
|
|
||||||
auto knownKind = proto->getKnownProtocolKind();
|
|
||||||
if (!knownKind) return false;
|
|
||||||
|
|
||||||
auto &ctx = nominal->getASTContext();
|
|
||||||
(void)ctx;
|
|
||||||
|
|
||||||
// Local function to handle resolution via lookup directly into the nominal
|
|
||||||
// type.
|
|
||||||
auto resolveViaLookup = [&] {
|
|
||||||
for (auto member : nominal->lookupDirect(assocType->getFullName())) {
|
|
||||||
auto memberType = dyn_cast<TypeDecl>(member);
|
|
||||||
if (!memberType) continue;
|
|
||||||
if (memberType->getDeclContext() != nominal) continue;
|
|
||||||
|
|
||||||
conformance->setTypeWitness(assocType,
|
|
||||||
nominal->mapTypeIntoContext(
|
|
||||||
memberType->getDeclaredInterfaceType()),
|
|
||||||
memberType);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// RawRepresentable.RawValue.
|
|
||||||
if (*knownKind == KnownProtocolKind::RawRepresentable) {
|
|
||||||
assert(assocType->getName() == ctx.Id_RawValue);
|
|
||||||
return resolveViaLookup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// OptionSet.Element.
|
|
||||||
if (*knownKind == KnownProtocolKind::OptionSet) {
|
|
||||||
assert(assocType->getName() == ctx.Id_Element);
|
|
||||||
return resolveViaLookup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpressibleByArrayLiteral.ArrayLiteralElement
|
|
||||||
if (*knownKind == KnownProtocolKind::ExpressibleByArrayLiteral) {
|
|
||||||
assert(assocType->getName() == ctx.Id_ArrayLiteralElement);
|
|
||||||
return resolveViaLookup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// _ObjectiveCBridgeable._ObjectiveCType
|
|
||||||
if (*knownKind == KnownProtocolKind::ObjectiveCBridgeable) {
|
|
||||||
assert(assocType->getName() == ctx.Id_ObjectiveCType);
|
|
||||||
return resolveViaLookup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// _BridgedStoredNSError.Code
|
|
||||||
if (*knownKind == KnownProtocolKind::BridgedStoredNSError) {
|
|
||||||
assert(assocType->getName() == ctx.Id_Code);
|
|
||||||
return resolveViaLookup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorCodeProtocol._ErrorType.
|
|
||||||
if (*knownKind == KnownProtocolKind::ErrorCodeProtocol) {
|
|
||||||
assert(assocType->getName() == ctx.Id_ErrorType);
|
|
||||||
return resolveViaLookup();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<Type, TypeDecl *>
|
std::pair<Type, TypeDecl *>
|
||||||
NormalProtocolConformance::getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
|
NormalProtocolConformance::getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
|
||||||
LazyResolver *resolver,
|
LazyResolver *resolver,
|
||||||
@@ -466,11 +388,9 @@ NormalProtocolConformance::getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
|
|||||||
|
|
||||||
// Otherwise, resolve the type witness.
|
// Otherwise, resolve the type witness.
|
||||||
PrettyStackTraceRequirement trace("resolving", this, assocType);
|
PrettyStackTraceRequirement trace("resolving", this, assocType);
|
||||||
if (!resolveKnownTypeWitness(const_cast<NormalProtocolConformance *>(this),
|
assert(resolver && "Unable to resolve type witness");
|
||||||
assocType)) {
|
resolver->resolveTypeWitness(this, assocType);
|
||||||
assert(resolver && "Unable to resolve type witness");
|
|
||||||
resolver->resolveTypeWitness(this, assocType);
|
|
||||||
}
|
|
||||||
known = TypeWitnesses.find(assocType);
|
known = TypeWitnesses.find(assocType);
|
||||||
assert(known != TypeWitnesses.end() && "Didn't resolve witness?");
|
assert(known != TypeWitnesses.end() && "Didn't resolve witness?");
|
||||||
return known->second;
|
return known->second;
|
||||||
|
|||||||
@@ -7359,6 +7359,42 @@ void ClangImporter::Implementation::finishPendingActions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Look up associated type requirements in the conforming type.
|
||||||
|
static void finishTypeWitnesses(
|
||||||
|
NormalProtocolConformance *conformance) {
|
||||||
|
auto *proto = conformance->getProtocol();
|
||||||
|
auto *nominal = conformance->getType()->getAnyNominal();
|
||||||
|
|
||||||
|
for (auto *req : proto->getMembers()) {
|
||||||
|
if (auto *assocType = dyn_cast<AssociatedTypeDecl>(req)) {
|
||||||
|
// FIXME: This should not happen?
|
||||||
|
if (conformance->hasTypeWitness(assocType)) continue;
|
||||||
|
|
||||||
|
bool satisfied = false;
|
||||||
|
|
||||||
|
for (auto member : nominal->lookupDirect(assocType->getFullName())) {
|
||||||
|
auto memberType = dyn_cast<TypeDecl>(member);
|
||||||
|
if (!memberType) continue;
|
||||||
|
|
||||||
|
conformance->setTypeWitness(assocType,
|
||||||
|
nominal->mapTypeIntoContext(
|
||||||
|
memberType->getDeclaredInterfaceType()),
|
||||||
|
memberType);
|
||||||
|
satisfied = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!satisfied) {
|
||||||
|
llvm::errs() << ("Cannot look up associated type for "
|
||||||
|
"imported conformance:\n");
|
||||||
|
conformance->getType().dump(llvm::errs());
|
||||||
|
assocType->dump(llvm::errs());
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Make sure any inherited conformances also get completed, if necessary.
|
/// Make sure any inherited conformances also get completed, if necessary.
|
||||||
static void finishInheritedConformances(
|
static void finishInheritedConformances(
|
||||||
NormalProtocolConformance *conformance) {
|
NormalProtocolConformance *conformance) {
|
||||||
@@ -7449,6 +7485,7 @@ void ClangImporter::Implementation::finishNormalConformance(
|
|||||||
conformance->getType());
|
conformance->getType());
|
||||||
PrettyStackTraceDecl traceTo("... to", proto);
|
PrettyStackTraceDecl traceTo("... to", proto);
|
||||||
|
|
||||||
|
finishTypeWitnesses(conformance);
|
||||||
finishInheritedConformances(conformance);
|
finishInheritedConformances(conformance);
|
||||||
finishSignatureConformances(conformance);
|
finishSignatureConformances(conformance);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user