Skip to content

Commit e26949d

Browse files
committed
ClangImporter: Find type witnesses in finishNormalConformance()
1 parent b7f744c commit e26949d

File tree

2 files changed

+40
-83
lines changed

2 files changed

+40
-83
lines changed

lib/AST/ProtocolConformance.cpp

Lines changed: 3 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -359,84 +359,6 @@ bool NormalProtocolConformance::hasTypeWitness(AssociatedTypeDecl *assocType,
359359
return false;
360360
}
361361

362-
/// Directly resolve type witnesses that are known to the compiler because they
363-
/// were synthesized by the compiler.
364-
///
365-
/// FIXME: This is a hack to work around the fact that we don't have a
366-
/// TypeChecker when we need one.
367-
///
368-
/// \returns true if we resolved the type witness.
369-
static bool resolveKnownTypeWitness(NormalProtocolConformance *conformance,
370-
AssociatedTypeDecl *assocType) {
371-
auto nominal = conformance->getType()->getAnyNominal();
372-
if (!nominal) return false;
373-
374-
if (!nominal->hasClangNode()) return false;
375-
376-
auto proto = conformance->getProtocol();
377-
auto knownKind = proto->getKnownProtocolKind();
378-
if (!knownKind) return false;
379-
380-
auto &ctx = nominal->getASTContext();
381-
(void)ctx;
382-
383-
// Local function to handle resolution via lookup directly into the nominal
384-
// type.
385-
auto resolveViaLookup = [&] {
386-
for (auto member : nominal->lookupDirect(assocType->getFullName())) {
387-
auto memberType = dyn_cast<TypeDecl>(member);
388-
if (!memberType) continue;
389-
if (memberType->getDeclContext() != nominal) continue;
390-
391-
conformance->setTypeWitness(assocType,
392-
nominal->mapTypeIntoContext(
393-
memberType->getDeclaredInterfaceType()),
394-
memberType);
395-
return true;
396-
}
397-
398-
return false;
399-
};
400-
401-
// RawRepresentable.RawValue.
402-
if (*knownKind == KnownProtocolKind::RawRepresentable) {
403-
assert(assocType->getName() == ctx.Id_RawValue);
404-
return resolveViaLookup();
405-
}
406-
407-
// OptionSet.Element.
408-
if (*knownKind == KnownProtocolKind::OptionSet) {
409-
assert(assocType->getName() == ctx.Id_Element);
410-
return resolveViaLookup();
411-
}
412-
413-
// ExpressibleByArrayLiteral.ArrayLiteralElement
414-
if (*knownKind == KnownProtocolKind::ExpressibleByArrayLiteral) {
415-
assert(assocType->getName() == ctx.Id_ArrayLiteralElement);
416-
return resolveViaLookup();
417-
}
418-
419-
// _ObjectiveCBridgeable._ObjectiveCType
420-
if (*knownKind == KnownProtocolKind::ObjectiveCBridgeable) {
421-
assert(assocType->getName() == ctx.Id_ObjectiveCType);
422-
return resolveViaLookup();
423-
}
424-
425-
// _BridgedStoredNSError.Code
426-
if (*knownKind == KnownProtocolKind::BridgedStoredNSError) {
427-
assert(assocType->getName() == ctx.Id_Code);
428-
return resolveViaLookup();
429-
}
430-
431-
// ErrorCodeProtocol._ErrorType.
432-
if (*knownKind == KnownProtocolKind::ErrorCodeProtocol) {
433-
assert(assocType->getName() == ctx.Id_ErrorType);
434-
return resolveViaLookup();
435-
}
436-
437-
return false;
438-
}
439-
440362
std::pair<Type, TypeDecl *>
441363
NormalProtocolConformance::getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
442364
LazyResolver *resolver,
@@ -466,11 +388,9 @@ NormalProtocolConformance::getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
466388

467389
// Otherwise, resolve the type witness.
468390
PrettyStackTraceRequirement trace("resolving", this, assocType);
469-
if (!resolveKnownTypeWitness(const_cast<NormalProtocolConformance *>(this),
470-
assocType)) {
471-
assert(resolver && "Unable to resolve type witness");
472-
resolver->resolveTypeWitness(this, assocType);
473-
}
391+
assert(resolver && "Unable to resolve type witness");
392+
resolver->resolveTypeWitness(this, assocType);
393+
474394
known = TypeWitnesses.find(assocType);
475395
assert(known != TypeWitnesses.end() && "Didn't resolve witness?");
476396
return known->second;

lib/ClangImporter/ImportDecl.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7359,6 +7359,42 @@ void ClangImporter::Implementation::finishPendingActions() {
73597359
}
73607360
}
73617361

7362+
/// Look up associated type requirements in the conforming type.
7363+
static void finishTypeWitnesses(
7364+
NormalProtocolConformance *conformance) {
7365+
auto *proto = conformance->getProtocol();
7366+
auto *nominal = conformance->getType()->getAnyNominal();
7367+
7368+
for (auto *req : proto->getMembers()) {
7369+
if (auto *assocType = dyn_cast<AssociatedTypeDecl>(req)) {
7370+
// FIXME: This should not happen?
7371+
if (conformance->hasTypeWitness(assocType)) continue;
7372+
7373+
bool satisfied = false;
7374+
7375+
for (auto member : nominal->lookupDirect(assocType->getFullName())) {
7376+
auto memberType = dyn_cast<TypeDecl>(member);
7377+
if (!memberType) continue;
7378+
7379+
conformance->setTypeWitness(assocType,
7380+
nominal->mapTypeIntoContext(
7381+
memberType->getDeclaredInterfaceType()),
7382+
memberType);
7383+
satisfied = true;
7384+
break;
7385+
}
7386+
7387+
if (!satisfied) {
7388+
llvm::errs() << ("Cannot look up associated type for "
7389+
"imported conformance:\n");
7390+
conformance->getType().dump(llvm::errs());
7391+
assocType->dump(llvm::errs());
7392+
abort();
7393+
}
7394+
}
7395+
}
7396+
}
7397+
73627398
/// Make sure any inherited conformances also get completed, if necessary.
73637399
static void finishInheritedConformances(
73647400
NormalProtocolConformance *conformance) {
@@ -7449,6 +7485,7 @@ void ClangImporter::Implementation::finishNormalConformance(
74497485
conformance->getType());
74507486
PrettyStackTraceDecl traceTo("... to", proto);
74517487

7488+
finishTypeWitnesses(conformance);
74527489
finishInheritedConformances(conformance);
74537490
finishSignatureConformances(conformance);
74547491

0 commit comments

Comments
 (0)