Skip to content

Commit d27b1c0

Browse files
authored
Merge pull request #11890 from slavapestov/divorce-clang-importer-from-sema-part-5
Reworking ClangImporter to not depend on Sema, part 5
2 parents 33b673e + ae5d6fd commit d27b1c0

File tree

2 files changed

+77
-145
lines changed

2 files changed

+77
-145
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: 74 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,34 +1212,31 @@ createValueConstructor(ClangImporter::Implementation &Impl,
12121212
return constructor;
12131213
}
12141214

1215-
static void populateInheritedTypes(NominalTypeDecl *nominal,
1216-
ArrayRef<ProtocolDecl *> protocols,
1217-
Type superclass = Type()) {
1215+
/// Add protocol conformances and synthesized protocol attributes
1216+
static void
1217+
populateInheritedTypes(ClangImporter::Implementation &Impl,
1218+
NominalTypeDecl *nominal,
1219+
ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1220+
Type superclass = Type()) {
12181221
SmallVector<TypeLoc, 4> inheritedTypes;
12191222
if (superclass)
12201223
inheritedTypes.push_back(TypeLoc::withoutLoc(superclass));
1221-
inheritedTypes.resize(protocols.size() + (superclass ? 1 : 0));
1222-
for_each(MutableArrayRef<TypeLoc>(inheritedTypes).drop_front(superclass?1:0),
1223-
protocols,
1224-
[](TypeLoc &tl, ProtocolDecl *proto) {
1225-
tl = TypeLoc::withoutLoc(proto->getDeclaredType());
1226-
});
1224+
1225+
for (auto protoKind : synthesizedProtocolAttrs) {
1226+
if (auto *protoDecl = Impl.SwiftContext.getProtocol(protoKind)) {
1227+
auto protoType = protoDecl->getDeclaredType();
1228+
inheritedTypes.push_back(TypeLoc::withoutLoc(protoType));
1229+
}
1230+
}
1231+
12271232
nominal->setInherited(nominal->getASTContext().AllocateCopy(inheritedTypes));
12281233
nominal->setCheckedInheritanceClause();
1229-
}
1230-
1231-
/// Add protocol conformances and synthesized protocol attributes
1232-
static void
1233-
addProtocolsToStruct(ClangImporter::Implementation &Impl,
1234-
StructDecl *structDecl,
1235-
ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1236-
ArrayRef<ProtocolDecl *> protocols) {
1237-
populateInheritedTypes(structDecl, protocols);
12381234

12391235
// Note synthesized protocols
1240-
for (auto kind : synthesizedProtocolAttrs)
1241-
structDecl->getAttrs().add(new (Impl.SwiftContext)
1242-
SynthesizedProtocolAttr(kind, &Impl));
1236+
for (auto kind : synthesizedProtocolAttrs) {
1237+
nominal->getAttrs().add(new (Impl.SwiftContext)
1238+
SynthesizedProtocolAttr(kind, &Impl));
1239+
}
12431240
}
12441241

12451242
/// Add a synthesized typealias to the given nominal type.
@@ -1264,7 +1261,6 @@ static void addSynthesizedTypealias(NominalTypeDecl *nominal, Identifier name,
12641261
/// \param structDecl the struct to make a raw value for
12651262
/// \param underlyingType the type of the raw value
12661263
/// \param synthesizedProtocolAttrs synthesized protocol attributes to add
1267-
/// \param protocols the protocols to make this struct conform to
12681264
/// \param setterAccess the access level of the raw value's setter
12691265
///
12701266
/// This will perform most of the work involved in making a new Swift struct
@@ -1275,11 +1271,11 @@ static void addSynthesizedTypealias(NominalTypeDecl *nominal, Identifier name,
12751271
static void makeStructRawValued(
12761272
ClangImporter::Implementation &Impl, StructDecl *structDecl,
12771273
Type underlyingType, ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1278-
ArrayRef<ProtocolDecl *> protocols,
12791274
MakeStructRawValuedOptions options = getDefaultMakeStructRawValuedOptions(),
12801275
AccessLevel setterAccess = AccessLevel::Private) {
12811276
auto &ctx = Impl.SwiftContext;
1282-
addProtocolsToStruct(Impl, structDecl, synthesizedProtocolAttrs, protocols);
1277+
1278+
populateInheritedTypes(Impl, structDecl, synthesizedProtocolAttrs);
12831279

12841280
// Create a variable to store the underlying value.
12851281
VarDecl *var;
@@ -1356,7 +1352,6 @@ static ConstructorDecl *createRawValueBridgingConstructor(
13561352
/// \param storedUnderlyingType the type of the stored raw value
13571353
/// \param bridgedType the type of the 'rawValue' computed property bridge
13581354
/// \param synthesizedProtocolAttrs synthesized protocol attributes to add
1359-
/// \param protocols the protocols to make this struct conform to
13601355
///
13611356
/// This will perform most of the work involved in making a new Swift struct
13621357
/// be backed by a stored raw value and computed raw value of bridged type.
@@ -1368,9 +1363,10 @@ static void makeStructRawValuedWithBridge(
13681363
ClangImporter::Implementation &Impl, StructDecl *structDecl,
13691364
Type storedUnderlyingType, Type bridgedType,
13701365
ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1371-
ArrayRef<ProtocolDecl *> protocols, bool makeUnlabeledValueInit = false) {
1366+
bool makeUnlabeledValueInit = false) {
13721367
auto &ctx = Impl.SwiftContext;
1373-
addProtocolsToStruct(Impl, structDecl, synthesizedProtocolAttrs, protocols);
1368+
1369+
populateInheritedTypes(Impl, structDecl, synthesizedProtocolAttrs);
13741370

13751371
auto storedVarName = ctx.getIdentifier("_rawValue");
13761372
auto computedVarName = ctx.Id_rawValue;
@@ -2411,7 +2407,6 @@ namespace {
24112407
if (!dc)
24122408
return nullptr;
24132409

2414-
ASTContext &ctx = Impl.SwiftContext;
24152410
auto name = importedName.getDeclName().getBaseIdentifier();
24162411

24172412
// Create the enum declaration and record it.
@@ -2440,19 +2435,14 @@ namespace {
24402435
AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
24412436
structDecl->computeType();
24422437

2443-
ProtocolDecl *protocols[]
2444-
= {ctx.getProtocol(KnownProtocolKind::RawRepresentable),
2445-
ctx.getProtocol(KnownProtocolKind::Equatable)};
2446-
if (!protocols[0] || !protocols[1])
2447-
return nullptr;
2448-
24492438
auto options = getDefaultMakeStructRawValuedOptions();
24502439
options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
24512440
options -= MakeStructRawValuedFlags::IsLet;
24522441
options -= MakeStructRawValuedFlags::IsImplicit;
24532442

24542443
makeStructRawValued(Impl, structDecl, underlyingType,
2455-
{KnownProtocolKind::RawRepresentable}, protocols,
2444+
{KnownProtocolKind::RawRepresentable,
2445+
KnownProtocolKind::Equatable},
24562446
options, /*setterAccess=*/AccessLevel::Public);
24572447

24582448
result = structDecl;
@@ -2495,15 +2485,8 @@ namespace {
24952485
errorWrapper->setAccess(AccessLevel::Public);
24962486

24972487
// Add inheritance clause.
2498-
TypeLoc inheritedTypes[1] = {
2499-
TypeLoc::withoutLoc(bridgedNSError->getDeclaredType())
2500-
};
2501-
errorWrapper->setInherited(C.AllocateCopy(inheritedTypes));
2502-
errorWrapper->setCheckedInheritanceClause();
2503-
2504-
// Set up error conformance to be lazily expanded
2505-
errorWrapper->getAttrs().add(new (C) SynthesizedProtocolAttr(
2506-
KnownProtocolKind::BridgedStoredNSError, &Impl));
2488+
populateInheritedTypes(Impl, errorWrapper,
2489+
{KnownProtocolKind::BridgedStoredNSError});
25072490

25082491
// Create the _nsError member.
25092492
// public let _nsError: NSError
@@ -2565,6 +2548,10 @@ namespace {
25652548
if (errorWrapper) {
25662549
inheritedTypes.push_back(
25672550
TypeLoc::withoutLoc(errorCodeProto->getDeclaredType()));
2551+
2552+
enumDecl->getAttrs().add(new (Impl.SwiftContext)
2553+
SynthesizedProtocolAttr(KnownProtocolKind::ErrorCodeProtocol,
2554+
&Impl));
25682555
}
25692556
enumDecl->setInherited(C.AllocateCopy(inheritedTypes));
25702557
enumDecl->setCheckedInheritanceClause();
@@ -4806,14 +4793,8 @@ SwiftDeclConverter::importCFClassType(const clang::TypedefNameDecl *decl,
48064793
addObjCAttribute(theClass, None);
48074794
Impl.registerExternalDecl(theClass);
48084795

4809-
auto *cfObjectProto =
4810-
Impl.SwiftContext.getProtocol(KnownProtocolKind::CFObject);
4811-
if (cfObjectProto) {
4812-
populateInheritedTypes(theClass, cfObjectProto, superclass);
4813-
auto *attr = new (Impl.SwiftContext) SynthesizedProtocolAttr(
4814-
KnownProtocolKind::CFObject, &Impl);
4815-
theClass->getAttrs().add(attr);
4816-
}
4796+
populateInheritedTypes(Impl, theClass, {KnownProtocolKind::CFObject},
4797+
superclass);
48174798

48184799
// Look for bridging attributes on the clang record. We can
48194800
// just check the most recent redeclaration, which will inherit
@@ -5001,15 +4982,11 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
50014982

50024983
// Determine the set of protocols to which the synthesized
50034984
// type will conform.
5004-
SmallVector<ProtocolDecl *, 4> protocols;
50054985
SmallVector<KnownProtocolKind, 4> synthesizedProtocols;
50064986

50074987
// Local function to add a known protocol.
50084988
auto addKnown = [&](KnownProtocolKind kind) {
5009-
if (auto proto = ctx.getProtocol(kind)) {
5010-
protocols.push_back(proto);
5011-
synthesizedProtocols.push_back(kind);
5012-
}
4989+
synthesizedProtocols.push_back(kind);
50134990
};
50144991

50154992
// Add conformances that are always available.
@@ -5032,7 +5009,6 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
50325009
if (conformsToProtocolInOriginalModule(computedNominal, proto,
50335010
Impl.tryLoadFoundationModule(),
50345011
Impl.getTypeResolver())) {
5035-
protocols.push_back(proto);
50365012
synthesizedProtocols.push_back(kind);
50375013
return true;
50385014
}
@@ -5055,13 +5031,13 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
50555031
options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
50565032

50575033
makeStructRawValued(Impl, structDecl, storedUnderlyingType,
5058-
synthesizedProtocols, protocols, options);
5034+
synthesizedProtocols, options);
50595035
} else {
50605036
// We need to make a stored rawValue or storage type, and a
50615037
// computed one of bridged type.
50625038
makeStructRawValuedWithBridge(Impl, structDecl, storedUnderlyingType,
50635039
computedPropertyUnderlyingType,
5064-
synthesizedProtocols, protocols,
5040+
synthesizedProtocols,
50655041
/*makeUnlabeledValueInit=*/unlabeledCtor);
50665042

50675043
if (transferredObjCBridgeable)
@@ -5220,9 +5196,8 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
52205196
decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
52215197
structDecl->computeType();
52225198

5223-
ProtocolDecl *protocols[] = {ctx.getProtocol(KnownProtocolKind::OptionSet)};
52245199
makeStructRawValued(Impl, structDecl, underlyingType,
5225-
{KnownProtocolKind::OptionSet}, protocols);
5200+
{KnownProtocolKind::OptionSet});
52265201
auto selfType = structDecl->getDeclaredInterfaceType();
52275202
addSynthesizedTypealias(structDecl, ctx.Id_Element, selfType);
52285203
addSynthesizedTypealias(structDecl, ctx.Id_ArrayLiteralElement, selfType);
@@ -7359,6 +7334,42 @@ void ClangImporter::Implementation::finishPendingActions() {
73597334
}
73607335
}
73617336

7337+
/// Look up associated type requirements in the conforming type.
7338+
static void finishTypeWitnesses(
7339+
NormalProtocolConformance *conformance) {
7340+
auto *proto = conformance->getProtocol();
7341+
auto *nominal = conformance->getType()->getAnyNominal();
7342+
7343+
for (auto *req : proto->getMembers()) {
7344+
if (auto *assocType = dyn_cast<AssociatedTypeDecl>(req)) {
7345+
// FIXME: This should not happen?
7346+
if (conformance->hasTypeWitness(assocType)) continue;
7347+
7348+
bool satisfied = false;
7349+
7350+
for (auto member : nominal->lookupDirect(assocType->getFullName())) {
7351+
auto memberType = dyn_cast<TypeDecl>(member);
7352+
if (!memberType) continue;
7353+
7354+
conformance->setTypeWitness(assocType,
7355+
nominal->mapTypeIntoContext(
7356+
memberType->getDeclaredInterfaceType()),
7357+
memberType);
7358+
satisfied = true;
7359+
break;
7360+
}
7361+
7362+
if (!satisfied) {
7363+
llvm::errs() << ("Cannot look up associated type for "
7364+
"imported conformance:\n");
7365+
conformance->getType().dump(llvm::errs());
7366+
assocType->dump(llvm::errs());
7367+
abort();
7368+
}
7369+
}
7370+
}
7371+
}
7372+
73627373
/// Make sure any inherited conformances also get completed, if necessary.
73637374
static void finishInheritedConformances(
73647375
NormalProtocolConformance *conformance) {
@@ -7449,6 +7460,7 @@ void ClangImporter::Implementation::finishNormalConformance(
74497460
conformance->getType());
74507461
PrettyStackTraceDecl traceTo("... to", proto);
74517462

7463+
finishTypeWitnesses(conformance);
74527464
finishInheritedConformances(conformance);
74537465
finishSignatureConformances(conformance);
74547466

0 commit comments

Comments
 (0)