Skip to content

Commit 18df1c1

Browse files
committed
GSB: Simplify representation of FloatingRequirementSource
1 parent b717138 commit 18df1c1

File tree

2 files changed

+67
-79
lines changed

2 files changed

+67
-79
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,7 @@ class GenericSignatureBuilder::RequirementSource final
11291129
/// parameter or result type of a generic function.
11301130
static const RequirementSource *forInferred(GenericSignatureBuilder &builder,
11311131
Type rootType,
1132-
const TypeRepr *typeRepr);
1132+
WrittenRequirementLoc writtenLoc);
11331133

11341134
/// Retrieve a requirement source representing the requirement signature
11351135
/// computation for a protocol.
@@ -1352,70 +1352,71 @@ class GenericSignatureBuilder::RequirementSource final
13521352
/// The root will be supplied as soon as the appropriate dependent type is
13531353
/// resolved.
13541354
class GenericSignatureBuilder::FloatingRequirementSource {
1355-
enum Kind {
1355+
enum Kind : uint8_t {
13561356
/// A fully-resolved requirement source, which does not need a root.
13571357
Resolved,
1358-
/// An explicit requirement source lacking a root.
1358+
/// An explicit requirement in a generic signature.
13591359
Explicit,
1360-
/// An inferred requirement source lacking a root.
1360+
/// A requirement inferred from a concrete type application in a
1361+
/// generic signature.
13611362
Inferred,
1362-
/// A requirement source augmented by an abstract protocol requirement
1363-
AbstractProtocol,
1363+
/// An explicit requirement written inside a protocol.
1364+
ProtocolRequirement,
1365+
/// A requirement inferred from a concrete type application inside a
1366+
/// protocol.
1367+
InferredProtocolRequirement,
13641368
/// A requirement source for a nested-type-name match introduced by
13651369
/// the given source.
13661370
NestedTypeNameMatch,
13671371
} kind;
13681372

1369-
using Storage =
1370-
llvm::PointerUnion<const RequirementSource *, const TypeRepr *,
1371-
const RequirementRepr *>;
1372-
1373-
Storage storage;
1373+
const RequirementSource *source;
1374+
WrittenRequirementLoc loc;
13741375

13751376
// Additional storage for an abstract protocol requirement.
13761377
union {
1377-
struct {
1378-
ProtocolDecl *protocol = nullptr;
1379-
WrittenRequirementLoc written;
1380-
bool inferred = false;
1381-
} protocolReq;
1382-
1378+
ProtocolDecl *protocol = nullptr;
13831379
Identifier nestedName;
13841380
};
13851381

1386-
FloatingRequirementSource(Kind kind, Storage storage)
1387-
: kind(kind), storage(storage) { }
1382+
FloatingRequirementSource(Kind kind, const RequirementSource *source)
1383+
: kind(kind), source(source) { }
13881384

13891385
public:
13901386
/// Implicit conversion from a resolved requirement source.
13911387
FloatingRequirementSource(const RequirementSource *source)
13921388
: FloatingRequirementSource(Resolved, source) { }
13931389

13941390
static FloatingRequirementSource forAbstract() {
1395-
return { Explicit, Storage() };
1391+
return { Explicit, nullptr };
13961392
}
13971393

13981394
static FloatingRequirementSource forExplicit(const TypeRepr *typeRepr) {
1399-
return { Explicit, typeRepr };
1395+
FloatingRequirementSource result{ Explicit, nullptr };
1396+
result.loc = typeRepr;
1397+
return result;
14001398
}
14011399

14021400
static FloatingRequirementSource forExplicit(
14031401
const RequirementRepr *requirementRepr) {
1404-
return { Explicit, requirementRepr };
1402+
FloatingRequirementSource result{ Explicit, nullptr };
1403+
result.loc = requirementRepr;
1404+
return result;
14051405
}
14061406

14071407
static FloatingRequirementSource forInferred(const TypeRepr *typeRepr) {
1408-
return { Inferred, typeRepr };
1408+
FloatingRequirementSource result{ Inferred, nullptr };
1409+
result.loc = typeRepr;
1410+
return result;
14091411
}
14101412

14111413
static FloatingRequirementSource viaProtocolRequirement(
14121414
const RequirementSource *base,
14131415
ProtocolDecl *inProtocol,
14141416
bool inferred) {
1415-
FloatingRequirementSource result{ AbstractProtocol, base };
1416-
result.protocolReq.protocol = inProtocol;
1417-
result.protocolReq.written = WrittenRequirementLoc();
1418-
result.protocolReq.inferred = inferred;
1417+
auto kind = (inferred ? InferredProtocolRequirement : ProtocolRequirement);
1418+
FloatingRequirementSource result{ kind, base };
1419+
result.protocol = inProtocol;
14191420
return result;
14201421
}
14211422

@@ -1424,16 +1425,16 @@ class GenericSignatureBuilder::FloatingRequirementSource {
14241425
ProtocolDecl *inProtocol,
14251426
WrittenRequirementLoc written,
14261427
bool inferred) {
1427-
FloatingRequirementSource result{ AbstractProtocol, base };
1428-
result.protocolReq.protocol = inProtocol;
1429-
result.protocolReq.written = written;
1430-
result.protocolReq.inferred = inferred;
1428+
auto kind = (inferred ? InferredProtocolRequirement : ProtocolRequirement);
1429+
FloatingRequirementSource result{ kind, base };
1430+
result.protocol = inProtocol;
1431+
result.loc = written;
14311432
return result;
14321433
}
14331434

14341435
static FloatingRequirementSource forNestedTypeNameMatch(
14351436
Identifier nestedName) {
1436-
FloatingRequirementSource result{ NestedTypeNameMatch, Storage() };
1437+
FloatingRequirementSource result{ NestedTypeNameMatch, nullptr };
14371438
result.nestedName = nestedName;
14381439
return result;
14391440
};

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 34 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,8 +1158,7 @@ const RequirementSource *RequirementSource::forExplicit(
11581158
const RequirementSource *RequirementSource::forInferred(
11591159
GenericSignatureBuilder &builder,
11601160
Type rootType,
1161-
const TypeRepr *typeRepr) {
1162-
WrittenRequirementLoc writtenLoc = typeRepr;
1161+
WrittenRequirementLoc writtenLoc) {
11631162
REQUIREMENT_SOURCE_FACTORY_BODY(
11641163
(nodeID, Inferred, nullptr, rootType.getPointer(),
11651164
writtenLoc.getOpaqueValue(), nullptr),
@@ -1646,40 +1645,34 @@ const RequirementSource *FloatingRequirementSource::getSource(
16461645
ResolvedType type) const {
16471646
switch (kind) {
16481647
case Resolved:
1649-
return storage.get<const RequirementSource *>();
1648+
return source;
16501649

16511650
case Explicit: {
16521651
auto depType = type.getDependentType(builder);
1653-
1654-
if (auto requirementRepr = storage.dyn_cast<const RequirementRepr *>())
1655-
return RequirementSource::forExplicit(builder, depType, requirementRepr);
1656-
if (auto typeRepr = storage.dyn_cast<const TypeRepr *>())
1657-
return RequirementSource::forExplicit(builder, depType, typeRepr);
1658-
return RequirementSource::forAbstract(builder, depType);
1652+
return RequirementSource::forExplicit(builder, depType, loc);
16591653
}
16601654

16611655
case Inferred: {
16621656
auto depType = type.getDependentType(builder);
1663-
return RequirementSource::forInferred(builder, depType,
1664-
storage.get<const TypeRepr *>());
1657+
return RequirementSource::forInferred(builder, depType, loc);
16651658
}
16661659

1667-
case AbstractProtocol: {
1660+
case ProtocolRequirement:
1661+
case InferredProtocolRequirement: {
16681662
auto depType = type.getDependentType();
16691663

16701664
// Derive the dependent type on which this requirement was written. It is
16711665
// the path from the requirement source on which this requirement is based
16721666
// to the potential archetype on which the requirement is being placed.
1673-
auto baseSource = storage.get<const RequirementSource *>();
1674-
auto baseSourceType = baseSource->getAffectedType();
1667+
auto baseSourceType = source->getAffectedType();
16751668

16761669
auto dependentType =
1677-
formProtocolRelativeType(protocolReq.protocol, baseSourceType, depType);
1670+
formProtocolRelativeType(protocol, baseSourceType, depType);
16781671

1679-
return storage.get<const RequirementSource *>()
1680-
->viaProtocolRequirement(builder, dependentType,
1681-
protocolReq.protocol, protocolReq.inferred,
1682-
protocolReq.written);
1672+
return source
1673+
->viaProtocolRequirement(builder, dependentType, protocol,
1674+
kind == InferredProtocolRequirement,
1675+
loc);
16831676
}
16841677

16851678
case NestedTypeNameMatch: {
@@ -1688,29 +1681,20 @@ const RequirementSource *FloatingRequirementSource::getSource(
16881681
}
16891682
}
16901683

1691-
llvm_unreachable("Unhandled FloatingPointRequirementSourceKind in switch.");
1684+
llvm_unreachable("unhandled kind");
16921685
}
16931686

16941687
SourceLoc FloatingRequirementSource::getLoc() const {
1695-
// For an explicit abstract protocol source, we can get a more accurate source
1696-
// location from the written protocol requirement.
1697-
if (kind == Kind::AbstractProtocol && isExplicit()) {
1698-
auto written = protocolReq.written;
1699-
if (auto typeRepr = written.dyn_cast<const TypeRepr *>())
1688+
if (kind == Inferred || isExplicit()) {
1689+
if (auto typeRepr = loc.dyn_cast<const TypeRepr *>())
17001690
return typeRepr->getLoc();
1701-
if (auto requirementRepr = written.dyn_cast<const RequirementRepr *>())
1691+
if (auto requirementRepr = loc.dyn_cast<const RequirementRepr *>())
17021692
return requirementRepr->getSeparatorLoc();
17031693
}
17041694

1705-
if (auto source = storage.dyn_cast<const RequirementSource *>())
1695+
if (source)
17061696
return source->getLoc();
17071697

1708-
if (auto typeRepr = storage.dyn_cast<const TypeRepr *>())
1709-
return typeRepr->getLoc();
1710-
1711-
if (auto requirementRepr = storage.dyn_cast<const RequirementRepr *>())
1712-
return requirementRepr->getSeparatorLoc();
1713-
17141698
return SourceLoc();
17151699
}
17161700

@@ -1721,8 +1705,9 @@ bool FloatingRequirementSource::isDerived() const {
17211705
case NestedTypeNameMatch:
17221706
return false;
17231707

1724-
case AbstractProtocol:
1725-
switch (storage.get<const RequirementSource *>()->kind) {
1708+
case ProtocolRequirement:
1709+
case InferredProtocolRequirement:
1710+
switch (source->kind) {
17261711
case RequirementSource::RequirementSignatureSelf:
17271712
return false;
17281713

@@ -1740,7 +1725,7 @@ bool FloatingRequirementSource::isDerived() const {
17401725
}
17411726

17421727
case Resolved:
1743-
return storage.get<const RequirementSource *>()->isDerivedRequirement();
1728+
return source->isDerivedRequirement();
17441729
}
17451730
llvm_unreachable("unhandled kind");
17461731
}
@@ -1754,14 +1739,14 @@ bool FloatingRequirementSource::isExplicit() const {
17541739
case NestedTypeNameMatch:
17551740
return false;
17561741

1757-
case AbstractProtocol:
1742+
case ProtocolRequirement:
17581743
// Requirements implied by other protocol conformance requirements are
17591744
// implicit, except when computing a requirement signature, where
17601745
// non-inferred ones are explicit, to allow flagging of redundant
17611746
// requirements.
1762-
switch (storage.get<const RequirementSource *>()->kind) {
1747+
switch (source->kind) {
17631748
case RequirementSource::RequirementSignatureSelf:
1764-
return !protocolReq.inferred;
1749+
return true;
17651750

17661751
case RequirementSource::Concrete:
17671752
case RequirementSource::Explicit:
@@ -1776,14 +1761,16 @@ bool FloatingRequirementSource::isExplicit() const {
17761761
return false;
17771762
}
17781763

1764+
case InferredProtocolRequirement:
1765+
return false;
1766+
17791767
case Resolved:
1780-
switch (storage.get<const RequirementSource *>()->kind) {
1768+
switch (source->kind) {
17811769
case RequirementSource::Explicit:
17821770
return true;
17831771

17841772
case RequirementSource::ProtocolRequirement:
1785-
return storage.get<const RequirementSource *>()->parent->kind
1786-
== RequirementSource::RequirementSignatureSelf;
1773+
return source->parent->kind == RequirementSource::RequirementSignatureSelf;
17871774

17881775
case RequirementSource::Inferred:
17891776
case RequirementSource::InferredProtocolRequirement:
@@ -1812,9 +1799,9 @@ FloatingRequirementSource FloatingRequirementSource::asInferred(
18121799
case NestedTypeNameMatch:
18131800
return *this;
18141801

1815-
case AbstractProtocol:
1816-
return viaProtocolRequirement(storage.get<const RequirementSource *>(),
1817-
protocolReq.protocol, typeRepr,
1802+
case ProtocolRequirement:
1803+
case InferredProtocolRequirement:
1804+
return viaProtocolRequirement(source, protocol, typeRepr,
18181805
/*inferred=*/true);
18191806
}
18201807
llvm_unreachable("unhandled kind");
@@ -1823,8 +1810,8 @@ FloatingRequirementSource FloatingRequirementSource::asInferred(
18231810
bool FloatingRequirementSource::isRecursive(
18241811
GenericSignatureBuilder &builder) const {
18251812
llvm::SmallSet<std::pair<CanType, ProtocolDecl *>, 32> visitedAssocReqs;
1826-
for (auto storedSource = storage.dyn_cast<const RequirementSource *>();
1827-
storedSource; storedSource = storedSource->parent) {
1813+
for (auto storedSource = source; storedSource;
1814+
storedSource = storedSource->parent) {
18281815
// FIXME: isRecursive() is completely misnamed
18291816
if (storedSource->kind == RequirementSource::EquivalentType)
18301817
return true;

0 commit comments

Comments
 (0)