Skip to content

Commit 23b1690

Browse files
committed
ASTPrinter: Refactor printing of RequirementSignatures
1 parent 2355cb4 commit 23b1690

10 files changed

+164
-79
lines changed

include/swift/AST/RequirementSignature.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ class RequirementSignature final {
7373
GenericSignatureErrors getErrors() const {
7474
return Errors;
7575
}
76+
77+
void getRequirementsWithInverses(
78+
ProtocolDecl *owner,
79+
SmallVector<Requirement, 2> &reqs,
80+
SmallVector<InverseRequirement, 2> &inverses) const;
81+
82+
void print(ProtocolDecl *owner, raw_ostream &OS,
83+
const PrintOptions &Options = PrintOptions()) const;
84+
void print(ProtocolDecl *owner, ASTPrinter &Printer,
85+
const PrintOptions &Opts = PrintOptions()) const;
7686
};
7787

7888
} // end namespace swift

lib/AST/ASTPrinter.cpp

Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,10 @@ class PrintAST : public ASTVisitor<PrintAST> {
970970
ArrayRef<InverseRequirement> inverses,
971971
bool &isFirstReq, unsigned flags,
972972
llvm::function_ref<bool(const Requirement &)> filter);
973+
void printRequirementSignature(ProtocolDecl *owner,
974+
RequirementSignature sig,
975+
unsigned flags,
976+
TypeDecl *attachingTo);
973977
void printRequirement(const Requirement &req);
974978
void printRequirement(const InverseRequirement &inverse,
975979
bool forInherited);
@@ -1566,46 +1570,20 @@ bestRequirementPrintLocation(ProtocolDecl *proto, const Requirement &req) {
15661570
}
15671571

15681572
void PrintAST::printInheritedFromRequirementSignature(ProtocolDecl *proto,
1569-
TypeDecl* attachingTo) {
1570-
Type attachedGP[1];
1571-
if (auto proto = dyn_cast<ProtocolDecl>(attachingTo))
1572-
attachedGP[0] = proto->getSelfInterfaceType();
1573-
else if (auto assoc = dyn_cast<AssociatedTypeDecl>(attachingTo))
1574-
attachedGP[0] = assoc->getDeclaredInterfaceType();
1575-
else
1576-
llvm_unreachable("nonexhaustive");
1577-
1578-
printGenericSignature(
1579-
proto->getRequirementSignatureAsGenericSignature(),
1580-
PrintInherited,
1581-
[&](const Requirement &req) {
1582-
// Skip the inferred 'Self : AnyObject' constraint if this is an
1583-
// @objc protocol.
1584-
if ((req.getKind() == RequirementKind::Layout) &&
1585-
req.getFirstType()->isEqual(proto->getSelfInterfaceType()) &&
1586-
req.getLayoutConstraint()->getKind() ==
1587-
LayoutConstraintKind::Class &&
1588-
proto->isObjC()) {
1589-
return false;
1590-
}
1591-
1592-
auto location = bestRequirementPrintLocation(proto, req);
1593-
return location.AttachedTo == attachingTo && !location.InWhereClause;
1594-
});
1573+
TypeDecl *attachingTo) {
1574+
printRequirementSignature(
1575+
proto, proto->getRequirementSignature(),
1576+
PrintInherited | PrintInverseRequirements,
1577+
attachingTo);
15951578
}
15961579

15971580
void PrintAST::printWhereClauseFromRequirementSignature(ProtocolDecl *proto,
15981581
TypeDecl *attachingTo) {
1599-
unsigned flags = PrintRequirements;
1582+
unsigned flags = PrintRequirements | PrintInverseRequirements;
16001583
if (isa<AssociatedTypeDecl>(attachingTo))
16011584
flags |= SwapSelfAndDependentMemberType;
1602-
printGenericSignature(
1603-
proto->getRequirementSignatureAsGenericSignature(),
1604-
flags,
1605-
[&](const Requirement &req) {
1606-
auto location = bestRequirementPrintLocation(proto, req);
1607-
return location.AttachedTo == attachingTo && location.InWhereClause;
1608-
});
1585+
printRequirementSignature(proto, proto->getRequirementSignature(), flags,
1586+
attachingTo);
16091587
}
16101588

16111589
/// A helper function to return the depth of a requirement.
@@ -1926,6 +1904,62 @@ void PrintAST::printSingleDepthOfGenericSignature(
19261904
Printer << ">";
19271905
}
19281906

1907+
void PrintAST::printRequirementSignature(ProtocolDecl *owner,
1908+
RequirementSignature sig,
1909+
unsigned flags,
1910+
TypeDecl *attachingTo) {
1911+
SmallVector<Requirement, 2> requirements;
1912+
SmallVector<InverseRequirement, 2> inverses;
1913+
1914+
if (flags & PrintInverseRequirements) {
1915+
sig.getRequirementsWithInverses(owner, requirements, inverses);
1916+
} else {
1917+
requirements.append(sig.getRequirements().begin(),
1918+
sig.getRequirements().end());
1919+
}
1920+
1921+
if (attachingTo) {
1922+
llvm::erase_if(requirements,
1923+
[&](Requirement req) {
1924+
// Skip the inferred 'Self : AnyObject' constraint if this is an
1925+
// @objc protocol.
1926+
if ((req.getKind() == RequirementKind::Layout) &&
1927+
req.getFirstType()->isEqual(owner->getSelfInterfaceType()) &&
1928+
req.getLayoutConstraint()->getKind() ==
1929+
LayoutConstraintKind::Class &&
1930+
owner->isObjC()) {
1931+
return true;
1932+
}
1933+
1934+
auto location = bestRequirementPrintLocation(owner, req);
1935+
if (location.AttachedTo != attachingTo)
1936+
return true;
1937+
1938+
if (flags & PrintRequirements)
1939+
return !location.InWhereClause;
1940+
1941+
return location.InWhereClause;
1942+
});
1943+
1944+
auto interfaceTy =
1945+
(isa<ProtocolDecl>(attachingTo)
1946+
? cast<ProtocolDecl>(attachingTo)->getSelfInterfaceType()
1947+
: cast<AssociatedTypeDecl>(attachingTo)->getDeclaredInterfaceType());
1948+
1949+
llvm::erase_if(inverses,
1950+
[&](InverseRequirement req) {
1951+
// We print inverse requirements in the inheritance clause only.
1952+
if (flags & PrintRequirements)
1953+
return true;
1954+
return !req.subject->isEqual(interfaceTy);
1955+
});
1956+
}
1957+
1958+
printSingleDepthOfGenericSignature(
1959+
owner->getGenericSignature().getGenericParams(), requirements, inverses,
1960+
flags, [&](Requirement) { return true; });
1961+
}
1962+
19291963
void PrintAST::printRequirement(const Requirement &req) {
19301964
SmallVector<Type, 2> rootParameterPacks;
19311965
getTransformedType(req.getFirstType())
@@ -2786,13 +2820,12 @@ void PrintAST::printSynthesizedExtension(Type ExtendedType,
27862820
void PrintAST::printSynthesizedExtensionImpl(Type ExtendedType,
27872821
ExtensionDecl *ExtDecl) {
27882822
auto printRequirementsFrom = [&](ExtensionDecl *ED, bool &IsFirst) {
2789-
// NOTE: As with normal extensions, we do not collapse defaults.
27902823
auto Sig = ED->getGenericSignature();
27912824
printSingleDepthOfGenericSignature(Sig.getGenericParams(),
27922825
Sig.getRequirements(),
27932826
/*inverses=*/{},
27942827
IsFirst,
2795-
PrintRequirements,
2828+
PrintRequirements | PrintInverseRequirements,
27962829
[](const Requirement &Req){
27972830
return true;
27982831
});
@@ -7946,6 +7979,22 @@ void GenericSignature::print(ASTPrinter &Printer,
79467979
PrintAST(Printer, Opts).printGenericSignature(*this, flags);
79477980
}
79487981

7982+
void RequirementSignature::print(ProtocolDecl *owner,
7983+
raw_ostream &OS,
7984+
const PrintOptions &Opts) const {
7985+
StreamPrinter Printer(OS);
7986+
print(owner, Printer, Opts);
7987+
}
7988+
7989+
void RequirementSignature::print(ProtocolDecl *owner,
7990+
ASTPrinter &Printer,
7991+
const PrintOptions &Opts) const {
7992+
auto flags = PrintAST::PrintParams | PrintAST::PrintRequirements;
7993+
if (Opts.PrintInverseRequirements)
7994+
flags |= PrintAST::PrintInverseRequirements;
7995+
PrintAST(Printer, Opts).printRequirementSignature(owner, *this, flags, nullptr);
7996+
}
7997+
79497998
void Requirement::print(raw_ostream &os, const PrintOptions &opts) const {
79507999
StreamPrinter printer(os);
79518000
PrintAST(printer, opts).printRequirement(*this);

lib/AST/GenericSignature.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,63 @@ void GenericSignatureImpl::getRequirementsWithInverses(
12861286
continue;
12871287
}
12881288

1289+
reqs.push_back(req);
1290+
}
1291+
}
1292+
1293+
void RequirementSignature::getRequirementsWithInverses(
1294+
ProtocolDecl *owner,
1295+
SmallVector<Requirement, 2> &reqs,
1296+
SmallVector<InverseRequirement, 2> &inverses) const {
1297+
auto &ctx = owner->getASTContext();
1298+
1299+
if (!SWIFT_ENABLE_EXPERIMENTAL_NONCOPYABLE_GENERICS &&
1300+
!ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
1301+
reqs.append(getRequirements().begin(), getRequirements().end());
1302+
return;
1303+
}
1304+
1305+
auto sig = owner->getGenericSignature();
1306+
1307+
llvm::SmallDenseSet<CanType, 2> assocTypes;
1308+
1309+
auto visit = [&](Type interfaceType) {
1310+
assocTypes.insert(interfaceType->getCanonicalType());
1311+
1312+
// Any associated type declaration with a superclass bound or concrete type
1313+
// does not have an inverse.
1314+
if (sig->getSuperclassBound(interfaceType) ||
1315+
sig->getConcreteType(interfaceType))
1316+
return;
1317+
1318+
for (auto ip : InvertibleProtocolSet::full()) {
1319+
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
1320+
1321+
// If we can derive a conformance to this protocol, then don't add an
1322+
// inverse.
1323+
if (sig->requiresProtocol(interfaceType, proto))
1324+
continue;
1325+
1326+
// Nothing implies a conformance to this protocol, so record the inverse.
1327+
inverses.push_back({interfaceType, proto, SourceLoc()});
1328+
}
1329+
};
1330+
1331+
visit(owner->getSelfInterfaceType());
1332+
1333+
// Record the absence of conformances to invertible protocols.
1334+
for (auto assocType : owner->getAssociatedTypeMembers()) {
1335+
visit(assocType->getDeclaredInterfaceType());
1336+
}
1337+
1338+
// Filter out explicit conformances to invertible protocols.
1339+
for (auto req : getRequirements()) {
1340+
if (req.getKind() == RequirementKind::Conformance &&
1341+
assocTypes.count(req.getFirstType()->getCanonicalType()) &&
1342+
req.getProtocolDecl()->getInvertibleProtocolKind()) {
1343+
continue;
1344+
}
1345+
12891346
reqs.push_back(req);
12901347
}
12911348
}

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3449,28 +3449,18 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
34493449
TypeChecker::inferDefaultWitnesses(PD);
34503450

34513451
if (Ctx.TypeCheckerOpts.DebugGenericSignatures) {
3452-
auto sig = PD->getRequirementSignatureAsGenericSignature();
3453-
llvm::errs() << "\n";
3454-
llvm::errs() << "Protocol requirement signature:\n";
3452+
auto sig = PD->getRequirementSignature();
34553453
PD->dumpRef(llvm::errs());
34563454
llvm::errs() << "\n";
34573455
llvm::errs() << "Requirement signature: ";
34583456
PrintOptions Opts;
34593457
Opts.ProtocolQualifiedDependentMemberTypes = true;
3460-
Opts.PrintInverseRequirements = true;
3461-
sig->print(llvm::errs(), Opts);
3462-
llvm::errs() << "\n";
3463-
3464-
llvm::errs() << "Canonical requirement signature: ";
3465-
auto canSig =
3466-
CanGenericSignature::getCanonical(sig.getGenericParams(),
3467-
sig.getRequirements());
3468-
canSig->print(llvm::errs(), Opts);
3458+
Opts.PrintInverseRequirements =
3459+
Ctx.TypeCheckerOpts.DebugInverseRequirements;
3460+
sig.print(PD, llvm::errs(), Opts);
34693461
llvm::errs() << "\n";
34703462
}
34713463

3472-
dumpGenericSignature(Ctx, PD);
3473-
34743464
if (!reqSig.getErrors()) {
34753465
// Always verify signatures, even if building without asserts.
34763466
//

test/Frontend/debug-generic-signatures.swift

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,23 @@
11
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures %s 2>&1 | %FileCheck %s
22

3-
// CHECK: Generic signature: <Self where Self : P1>
4-
// CHECK-NEXT: Canonical generic signature: <τ_0_0 where τ_0_0 : P1>
53
// CHECK-LABEL: main.(file).P1@
64
// CHECK: Requirement signature: <Self>
7-
// CHECK-NEXT: Canonical requirement signature: <τ_0_0>
85
protocol P1 {
96
associatedtype A
107
func f() -> A
118
}
129

1310
// Recursion, and where clauses.
14-
// CHECK: Generic signature: <Self where Self : P2>
15-
// CHECK-NEXT: Canonical generic signature: <τ_0_0 where τ_0_0 : P2>
1611
// CHECK-LABEL: main.(file).P2@
17-
// CHECK: Requirement signature: <Self where Self.[P2]A : P2, Self.[P2]B : P2, Self.[P2]A.[P2]A == Self.[P2]B.[P2]A>
18-
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P2]A : P2, τ_0_0.[P2]B : P2, τ_0_0.[P2]A.[P2]A == τ_0_0.[P2]B.[P2]A>
12+
// CHECK-NEXT: Requirement signature: <Self where Self.[P2]A : P2, Self.[P2]B : P2, Self.[P2]A.[P2]A == Self.[P2]B.[P2]A>
1913
protocol P2 {
2014
associatedtype A: P2
2115
associatedtype B: P2 where Self.A.A == Self.B.A
2216
}
2317

2418
// Simpler recursion
25-
// CHECK: Generic signature: <Self where Self : P3>
26-
// CHECK-NEXT: Canonical generic signature: <τ_0_0 where τ_0_0 : P3>
2719
// CHECK-LABEL: main.(file).P3@
28-
// CHECK: Requirement signature: <Self where Self.[P3]A : P3>
29-
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P3]A : P3>
20+
// CHECK-NEXT: Requirement signature: <Self where Self.[P3]A : P3>
3021
protocol P3 {
3122
associatedtype A: P3
3223
}

test/Generics/conformance_requirement_with_protocol_typealias.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ protocol PWorse {
3131
protocol Q1 {}
3232
protocol Q2 {}
3333

34+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=P
35+
// CHECK-NEXT: Generic signature: <Self where Self : P>
3436
extension P {
3537
typealias B = (Q1 & Q2)
3638
}

test/Generics/derived_via_concrete_in_protocol.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,20 @@ class X3 { }
2323

2424
// CHECK-LABEL: .P25a@
2525
// CHECK-NEXT: Requirement signature: <Self where Self.[P25a]A == X24<Self.[P25a]B>, Self.[P25a]B : P20>
26-
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P25a]A == X24<τ_0_0.[P25a]B>, τ_0_0.[P25a]B : P20>
2726
protocol P25a {
2827
associatedtype A: P24 // expected-warning{{redundant conformance constraint 'X24<Self.B>' : 'P24'}}
2928
associatedtype B: P20 where A == X24<B>
3029
}
3130

3231
// CHECK-LABEL: .P25b@
3332
// CHECK-NEXT: Requirement signature: <Self where Self.[P25b]A == X24<Self.[P25b]B>, Self.[P25b]B : P20>
34-
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P25b]A == X24<τ_0_0.[P25b]B>, τ_0_0.[P25b]B : P20>
3533
protocol P25b {
3634
associatedtype A
3735
associatedtype B: P20 where A == X24<B>
3836
}
3937

4038
// CHECK-LABEL: .P27a@
4139
// CHECK-NEXT: Requirement signature: <Self where Self.[P27a]A == X26<Self.[P27a]B>, Self.[P27a]B : X3>
42-
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P27a]A == X26<τ_0_0.[P27a]B>, τ_0_0.[P27a]B : X3>
4340
protocol P27a {
4441
associatedtype A: P26 // expected-warning{{redundant conformance constraint 'X26<Self.B>' : 'P26'}}
4542

@@ -48,7 +45,6 @@ protocol P27a {
4845

4946
// CHECK-LABEL: .P27b@
5047
// CHECK-NEXT: Requirement signature: <Self where Self.[P27b]A == X26<Self.[P27b]B>, Self.[P27b]B : X3>
51-
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P27b]A == X26<τ_0_0.[P27b]B>, τ_0_0.[P27b]B : X3>
5248
protocol P27b {
5349
associatedtype A
5450
associatedtype B: X3 where A == X26<B>

test/Generics/requirement_inference.swift

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -282,23 +282,15 @@ struct X22<T, U> {
282282
U == X20<T> { }
283283
}
284284

285-
// CHECK: Generic signature: <Self where Self : P22>
286-
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P22>
287-
// CHECK: Protocol requirement signature:
288285
// CHECK: .P22@
289286
// CHECK-NEXT: Requirement signature: <Self where Self.[P22]A == X20<Self.[P22]B>, Self.[P22]B : P20>
290-
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P22]A == X20<τ_0_0.[P22]B>, τ_0_0.[P22]B : P20>
291287
protocol P22 {
292288
associatedtype A
293289
associatedtype B: P20 where A == X20<B>
294290
}
295291

296-
// CHECK: Generic signature: <Self where Self : P23>
297-
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P23>
298-
// CHECK: Protocol requirement signature:
299292
// CHECK: .P23@
300293
// CHECK-NEXT: Requirement signature: <Self where Self.[P23]A == X20<Self.[P23]B>, Self.[P23]B : P20>
301-
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P23]A == X20<τ_0_0.[P23]B>, τ_0_0.[P23]B : P20>
302294
protocol P23 {
303295
associatedtype A
304296
associatedtype B: P20
@@ -332,8 +324,7 @@ struct X28 : P2 {
332324
}
333325

334326
// CHECK-LABEL: .P28@
335-
// CHECK-NEXT: Requirement signature: <Self where Self : P3, Self.[P3]P3Assoc == X28>
336-
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0 : P3, τ_0_0.[P3]P3Assoc == X28>
327+
// CHECK: Requirement signature: <Self where Self : P3, Self.[P3]P3Assoc == X28>
337328
protocol P28: P3 {
338329
typealias P3Assoc = X28 // expected-warning{{typealias overriding associated type}}
339330
}

0 commit comments

Comments
 (0)