Skip to content

Commit 7204a69

Browse files
committed
AST: Clean up ExistentialLayout construction
1 parent 9f0564c commit 7204a69

File tree

4 files changed

+44
-78
lines changed

4 files changed

+44
-78
lines changed

include/swift/AST/Requirement.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -261,21 +261,6 @@ struct InverseRequirement {
261261
static void expandDefaults(ASTContext &ctx,
262262
ArrayRef<Type> gps,
263263
SmallVectorImpl<StructuralRequirement> &result);
264-
265-
/// Adds the inferred default protocols for an assumed generic parameter with
266-
/// respect to that parameter's inverses and existing required protocols.
267-
/// For example, if an inverse ~P exists, then P will not be added to the
268-
/// protocols list.
269-
///
270-
/// Similarly, if the protocols list has a protocol Q that already implies
271-
/// Copyable, then we will not add `Copyable` to the protocols list.
272-
///
273-
/// \param inverses the inverses '& ~P' that are applied to the generic param.
274-
/// \param protocols the existing required protocols, to which defaults will
275-
/// be appended.
276-
static void expandDefaults(ASTContext &ctx,
277-
InvertibleProtocolSet inverses,
278-
SmallVectorImpl<ProtocolDecl*> &protocols);
279264
};
280265

281266
} // end namespace swift

lib/AST/Requirement.cpp

Lines changed: 6 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -350,59 +350,12 @@ void InverseRequirement::expandDefaults(
350350
!ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics))
351351
return;
352352

353-
SmallVector<ProtocolDecl*, NumInvertibleProtocols> defaults;
354-
expandDefaults(ctx, /*inverses=*/{}, defaults);
355-
356-
// Fast-path.
357-
if (defaults.empty())
358-
return;
359-
360353
for (auto gp : gps) {
361-
for (auto *proto : defaults) {
362-
auto protoTy = proto->getDeclaredInterfaceType();
363-
result.push_back({{RequirementKind::Conformance, gp, protoTy},
364-
SourceLoc()});
354+
for (auto ip : InvertibleProtocolSet::full()) {
355+
auto proto = ctx.getProtocol(getKnownProtocolKind(ip));
356+
result.push_back({{RequirementKind::Conformance, gp,
357+
proto->getDeclaredInterfaceType()},
358+
SourceLoc()});
365359
}
366360
}
367-
}
368-
369-
void InverseRequirement::expandDefaults(
370-
ASTContext &ctx,
371-
InvertibleProtocolSet inverses,
372-
SmallVectorImpl<ProtocolDecl*> &protocols) {
373-
374-
// Skip unless noncopyable generics is enabled
375-
if (!ctx.LangOpts.hasFeature(swift::Feature::NoncopyableGenerics))
376-
return;
377-
378-
// Try to add all invertible protocols, unless:
379-
// - an inverse was provided
380-
// - an existing protocol already requires it
381-
for (auto ip : InvertibleProtocolSet::full()) {
382-
// This matches with `lookupExistentialConformance`'s use of 'inheritsFrom'.
383-
bool alreadyRequired = false;
384-
for (auto proto : protocols) {
385-
if (proto->isSpecificProtocol(getKnownProtocolKind(ip))
386-
|| proto->requiresInvertible(ip)) {
387-
alreadyRequired = true;
388-
break;
389-
}
390-
}
391-
392-
// If some protocol member already implies P, then we don't need to
393-
// add a requirement for P.
394-
if (alreadyRequired) {
395-
assert(!inverses.contains(ip) && "cannot require P and ~P");
396-
continue;
397-
}
398-
399-
// Nothing implies P, so unless there's an inverse ~P, add the requirement.
400-
if (inverses.contains(ip))
401-
continue;
402-
403-
auto proto = ctx.getProtocol(getKnownProtocolKind(ip));
404-
assert(proto && "missing Copyable/Escapable from stdlib!");
405-
406-
protocols.push_back(proto);
407-
}
408-
}
361+
}

lib/AST/Type.cpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,20 @@ bool TypeBase::allowsOwnership(const GenericSignatureImpl *sig) {
278278
return getCanonicalType().allowsOwnership(sig);
279279
}
280280

281+
static void expandDefaults(SmallVectorImpl<ProtocolDecl *> &protocols,
282+
InvertibleProtocolSet inverses,
283+
ASTContext &ctx) {
284+
if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
285+
for (auto ip : InvertibleProtocolSet::full()) {
286+
if (!inverses.contains(ip)) {
287+
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
288+
protocols.push_back(proto);
289+
}
290+
}
291+
}
281292

293+
ProtocolType::canonicalizeProtocols(protocols);
294+
}
282295

283296
ExistentialLayout::ExistentialLayout(CanProtocolType type) {
284297
auto *protoDecl = type->getDecl();
@@ -291,9 +304,7 @@ ExistentialLayout::ExistentialLayout(CanProtocolType type) {
291304
representsAnyObject = false;
292305

293306
protocols.push_back(protoDecl);
294-
295-
// NOTE: all the invertible protocols are usable from ObjC.
296-
InverseRequirement::expandDefaults(type->getASTContext(), {}, protocols);
307+
expandDefaults(protocols, InvertibleProtocolSet(), type->getASTContext());
297308
}
298309

299310
ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
@@ -326,13 +337,26 @@ ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
326337
protocols.push_back(protoDecl);
327338
}
328339

329-
representsAnyObject =
330-
hasExplicitAnyObject && !explicitSuperclass && getProtocols().empty();
340+
auto inverses = type->getInverses();
341+
expandDefaults(protocols, inverses, type->getASTContext());
342+
343+
representsAnyObject = [&]() {
344+
if (!hasExplicitAnyObject)
345+
return false;
346+
347+
if (explicitSuperclass)
348+
return false;
331349

332-
// NOTE: all the invertible protocols are usable from ObjC.
333-
InverseRequirement::expandDefaults(type->getASTContext(),
334-
type->getInverses(),
335-
protocols);
350+
if (!inverses.empty())
351+
return false;
352+
353+
for (auto *proto : protocols) {
354+
if (!proto->getInvertibleProtocolKind())
355+
return false;
356+
}
357+
358+
return true;
359+
}();
336360
}
337361

338362
ExistentialLayout::ExistentialLayout(CanParameterizedProtocolType type)
@@ -1503,6 +1527,10 @@ static void addProtocols(Type T,
15031527

15041528
static void canonicalizeProtocols(SmallVectorImpl<ProtocolDecl *> &protocols,
15051529
ParameterizedProtocolMap *parameterized) {
1530+
// Skip a bunch of useless work.
1531+
if (protocols.size() <= 1)
1532+
return;
1533+
15061534
llvm::SmallDenseMap<ProtocolDecl *, unsigned> known;
15071535
bool zappedAny = false;
15081536

test/SILOptimizer/dead_witness_module.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend -Onone -parse-stdlib -parse-as-library -module-name TestModule %S/Inputs/TestModule.swift -emit-module-path %t/TestModule.swiftmodule
2+
// RUN: %target-swift-frontend -Onone -parse-as-library -module-name TestModule %S/Inputs/TestModule.swift -emit-module-path %t/TestModule.swiftmodule
33
// RUN: %target-swift-frontend -O %s -I %t -emit-sil | %FileCheck %s
44

55
// DeadFunctionElimination may not remove a method from a witness table which

0 commit comments

Comments
 (0)