Skip to content

Commit c9b4103

Browse files
committed
---
yaml --- r: 345853 b: refs/heads/master c: ee4df9b h: refs/heads/master i: 345851: 21e754c
1 parent cf25190 commit c9b4103

File tree

6 files changed

+130
-12
lines changed

6 files changed

+130
-12
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 19e6dc8f9ee0f9edf0d6065c9dc24b1ed2a68eaf
2+
refs/heads/master: ee4df9bac9c10f15ad9b792cad2991ae43cad0b3
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/lib/Frontend/ParseableInterfaceSupport.cpp

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,15 @@ namespace {
466466
/// spelling of the protocol type, as well as the locality in the file), but it
467467
/// does work.
468468
class InheritedProtocolCollector {
469+
static const StringLiteral DummyProtocolName;
470+
469471
/// Protocols that will be included by the ASTPrinter without any extra work.
470472
SmallVector<ProtocolDecl *, 8> IncludedProtocols;
471473
/// Protocols that will not be printed by the ASTPrinter.
472474
SmallVector<ProtocolDecl *, 8> ExtraProtocols;
475+
/// Protocols that can be printed, but whose conformances are constrained with
476+
/// something that \e can't be printed.
477+
SmallVector<const ProtocolType *, 8> ConditionalConformanceProtocols;
473478

474479
/// For each type in \p directlyInherited, classify the protocols it refers to
475480
/// as included for printing or not, and record them in the appropriate
@@ -492,6 +497,23 @@ class InheritedProtocolCollector {
492497
}
493498
}
494499

500+
/// For each type in \p directlyInherited, record any protocols that we would
501+
/// have printed in ConditionalConformanceProtocols.
502+
void recordConditionalConformances(ArrayRef<TypeLoc> directlyInherited) {
503+
for (TypeLoc inherited : directlyInherited) {
504+
Type inheritedTy = inherited.getType();
505+
if (!inheritedTy || !inheritedTy->isExistentialType())
506+
continue;
507+
508+
ExistentialLayout layout = inheritedTy->getExistentialLayout();
509+
for (ProtocolType *protoTy : layout.getProtocols())
510+
if (isPublicOrUsableFromInline(protoTy))
511+
ConditionalConformanceProtocols.push_back(protoTy);
512+
// FIXME: This ignores layout constraints, but currently we don't support
513+
// any of those besides 'AnyObject'.
514+
}
515+
}
516+
495517
public:
496518
using PerTypeMap = llvm::MapVector<const NominalTypeDecl *,
497519
InheritedProtocolCollector>;
@@ -530,6 +552,21 @@ class InheritedProtocolCollector {
530552
collectProtocols(map, member);
531553
}
532554

555+
/// If \p D is an extension providing conditional conformances, record those
556+
/// in \p map.
557+
///
558+
/// \sa recordConditionalConformances
559+
static void collectSkippedConditionalConformances(PerTypeMap &map,
560+
const Decl *D) {
561+
auto *extension = dyn_cast<ExtensionDecl>(D);
562+
if (!extension || !extension->isConstrainedExtension())
563+
return;
564+
565+
const NominalTypeDecl *nominal = extension->getExtendedNominal();
566+
map[nominal].recordConditionalConformances(extension->getInherited());
567+
// No recursion here because extensions are never nested.
568+
}
569+
533570
/// If there were any public protocols that need to be printed (i.e. they
534571
/// weren't conformed to explicitly or inherited by another printed protocol),
535572
/// do so now by printing a dummy extension on \p nominal to \p out.
@@ -580,7 +617,40 @@ class InheritedProtocolCollector {
580617
}, [&out] { out << ", "; });
581618
out << " {}\n";
582619
}
620+
621+
/// If there were any conditional conformances that couldn't be printed,
622+
/// make a dummy extension that conforms to all of them, constrained by a
623+
/// fake protocol.
624+
bool printInaccessibleConformanceExtensionIfNeeded(
625+
raw_ostream &out, const PrintOptions &printOptions,
626+
const NominalTypeDecl *nominal) const {
627+
if (ConditionalConformanceProtocols.empty())
628+
return false;
629+
assert(nominal->isGenericContext());
630+
631+
out << "extension ";
632+
nominal->getDeclaredType().print(out, printOptions);
633+
out << " : ";
634+
swift::interleave(ConditionalConformanceProtocols,
635+
[&out, &printOptions](const ProtocolType *protoTy) {
636+
protoTy->print(out, printOptions);
637+
}, [&out] { out << ", "; });
638+
out << " where "
639+
<< nominal->getGenericParamsOfContext()->getParams().front()->getName()
640+
<< " : " << DummyProtocolName << " {}\n";
641+
return true;
642+
}
643+
644+
/// Print a fake protocol declaration for use by
645+
/// #printInaccessibleConformanceExtensionIfNeeded.
646+
static void printDummyProtocolDeclaration(raw_ostream &out) {
647+
out << "\n@usableFromInline\ninternal protocol " << DummyProtocolName
648+
<< " {}\n";
649+
}
583650
};
651+
652+
const StringLiteral InheritedProtocolCollector::DummyProtocolName =
653+
"_ConstraintThatIsNotPartOfTheAPIOfThisLibrary";
584654
} // end anonymous namespace
585655

586656
bool swift::emitParseableInterface(raw_ostream &out,
@@ -597,8 +667,12 @@ bool swift::emitParseableInterface(raw_ostream &out,
597667
SmallVector<Decl *, 16> topLevelDecls;
598668
M->getTopLevelDecls(topLevelDecls);
599669
for (const Decl *D : topLevelDecls) {
600-
if (!D->shouldPrintInContext(printOptions))
670+
if (!D->shouldPrintInContext(printOptions) ||
671+
!printOptions.CurrentPrintabilityChecker->shouldPrint(D, printOptions)){
672+
InheritedProtocolCollector::collectSkippedConditionalConformances(
673+
inheritedProtocolMap, D);
601674
continue;
675+
}
602676

603677
D->print(out, printOptions);
604678
out << "\n";
@@ -607,11 +681,18 @@ bool swift::emitParseableInterface(raw_ostream &out,
607681
}
608682

609683
// Print dummy extensions for any protocols that were indirectly conformed to.
684+
bool needDummyProtocolDeclaration = false;
610685
for (const auto &nominalAndCollector : inheritedProtocolMap) {
686+
const NominalTypeDecl *nominal = nominalAndCollector.first;
611687
const InheritedProtocolCollector &collector = nominalAndCollector.second;
612-
collector.printSynthesizedExtensionIfNeeded(out, printOptions,
613-
nominalAndCollector.first);
688+
collector.printSynthesizedExtensionIfNeeded(out, printOptions, nominal);
689+
needDummyProtocolDeclaration |=
690+
collector.printInaccessibleConformanceExtensionIfNeeded(out,
691+
printOptions,
692+
nominal);
614693
}
694+
if (needDummyProtocolDeclaration)
695+
InheritedProtocolCollector::printDummyProtocolDeclaration(out);
615696

616697
return false;
617698
}

trunk/lib/SILGen/SILGenType.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -823,11 +823,13 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
823823
genVTable.emitVTable();
824824
}
825825

826-
// Build a default witness table if this is a protocol.
826+
// Build a default witness table if this is a protocol that needs one.
827827
if (auto protocol = dyn_cast<ProtocolDecl>(theType)) {
828-
if (!protocol->isObjC() &&
829-
protocol->isResilient())
830-
SGM.emitDefaultWitnessTable(protocol);
828+
if (!protocol->isObjC() && protocol->isResilient()) {
829+
auto *SF = protocol->getParentSourceFile();
830+
if (!SF || SF->Kind != SourceFileKind::Interface)
831+
SGM.emitDefaultWitnessTable(protocol);
832+
}
831833
return;
832834
}
833835

trunk/lib/Sema/TypeCheckDecl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3155,14 +3155,15 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
31553155
if (!PD->hasValidSignature())
31563156
return;
31573157

3158+
auto *SF = PD->getParentSourceFile();
31583159
{
31593160
// Check for circular inheritance within the protocol.
31603161
SmallVector<ProtocolDecl *, 8> path;
31613162
path.push_back(PD);
31623163
checkCircularity(TC, PD, diag::circular_protocol_def,
31633164
DescriptiveDeclKind::Protocol, path);
31643165

3165-
if (auto *SF = PD->getParentSourceFile()) {
3166+
if (SF) {
31663167
if (auto *tracker = SF->getReferencedNameTracker()) {
31673168
bool isNonPrivate =
31683169
(PD->getFormalAccess() > AccessLevel::FilePrivate);
@@ -3184,7 +3185,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
31843185

31853186
TC.checkDeclCircularity(PD);
31863187
if (PD->isResilient())
3187-
TC.inferDefaultWitnesses(PD);
3188+
if (!SF || SF->Kind != SourceFileKind::Interface)
3189+
TC.inferDefaultWitnesses(PD);
31883190

31893191
if (TC.Context.LangOpts.DebugGenericSignatures) {
31903192
auto requirementsSig =

trunk/test/ParseableInterface/Conformances.swiftinterface

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// swift-module-flags:
33

44
// RUN: %empty-directory(%t)
5-
// RUN: %target-swift-frontend -emit-module -enable-resilience -o %t/Conformances.swiftmodule %s
5+
// RUN: %target-swift-frontend -emit-module-path %t/Conformances.swiftmodule -enable-resilience -emit-sil -o %t/Conformances.sil %s
6+
// RUN: %FileCheck -check-prefix CHECK-MODULE %s < %t/Conformances.sil
7+
// RUN: %FileCheck -check-prefix NEGATIVE-MODULE %s < %t/Conformances.sil
68
// RUN: %target-swift-frontend -emit-sil -I %t %S/Inputs/ConformancesUser.swift -O | %FileCheck %s
79

810
public protocol MyProto {
@@ -11,6 +13,15 @@ public protocol MyProto {
1113
var prop: Int { get set }
1214
subscript(index: Int) -> Int { get set }
1315
}
16+
extension MyProto {
17+
public func method() {}
18+
}
19+
20+
// Make sure there's no default witness table. (But also make sure we printed at
21+
// least some regular witness tables, or we'll have to change the test.)
22+
// CHECK-MODULE: sil_witness_table{{.+}}: MyProto module Conformances
23+
// NEGATIVE-MODULE-NOT: sil_default_witness_table{{.+}}MyProto
24+
1425

1526
@_fixed_layout // allow conformance devirtualization
1627
public struct FullStructImpl: MyProto {
@@ -31,7 +42,8 @@ public struct OpaqueStructImpl: MyProto {}
3142

3243
// CHECK-LABEL: sil @$s16ConformancesUser10testOpaqueSiyF
3344
// CHECK: function_ref @$s12Conformances7MyProtoPxycfC
34-
// CHECK: function_ref @$s12Conformances7MyProtoP6methodyyF
45+
// Note the default implementation is filled in here.
46+
// CHECK: function_ref @$s12Conformances7MyProtoPAAE6methodyyF
3547
// CHECK: function_ref @$s12Conformances7MyProtoP4propSivs
3648
// CHECK: function_ref @$s12Conformances7MyProtoPyS2icig
3749
// CHECK: end sil function '$s16ConformancesUser10testOpaqueSiyF'

trunk/test/ParseableInterface/conformances.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,18 @@ public struct OuterGeneric<T> {
8181
// CHECK-NEXT: {{^ }$}}
8282
}
8383
// CHECK-NEXT: {{^}$}}
84+
85+
public protocol ConditionallyConformed {}
86+
public protocol ConditionallyConformedAgain {}
87+
88+
// CHECK-END: extension conformances.OuterGeneric : ConditionallyConformed, ConditionallyConformedAgain where T : _ConstraintThatIsNotPartOfTheAPIOfThisLibrary {}
89+
extension OuterGeneric: ConditionallyConformed where T: PrivateProto {}
90+
extension OuterGeneric: ConditionallyConformedAgain where T == PrivateProto {}
91+
8492
// CHECK-END: extension conformances.OuterGeneric.Inner : PublicBaseProto {}
93+
// CHECK-END: extension conformances.OuterGeneric.Inner : ConditionallyConformed, ConditionallyConformedAgain where T : _ConstraintThatIsNotPartOfTheAPIOfThisLibrary {}
94+
extension OuterGeneric.Inner: ConditionallyConformed where T: PrivateProto {}
95+
extension OuterGeneric.Inner: ConditionallyConformedAgain where T == PrivateProto {}
8596

8697
private protocol AnotherPrivateSubProto: PublicBaseProto {}
8798

@@ -147,3 +158,13 @@ private protocol BaseConstrainedProto: Base, PublicProto {}
147158
public class H1: Base, ClassConstrainedProto {}
148159
// CHECK: public class H1 : Base {
149160
// CHECK-END: extension conformances.H1 : PublicProto {}
161+
162+
public struct MultiGeneric<T, U, V> {}
163+
extension MultiGeneric: PublicProto where U: PrivateProto {}
164+
165+
// CHECK: public struct MultiGeneric<T, U, V> {
166+
// CHECK-END: extension conformances.MultiGeneric : PublicProto where T : _ConstraintThatIsNotPartOfTheAPIOfThisLibrary {}
167+
168+
169+
// CHECK-END: @usableFromInline
170+
// CHECK-END-NEXT: internal protocol _ConstraintThatIsNotPartOfTheAPIOfThisLibrary {}

0 commit comments

Comments
 (0)